質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

1402閲覧

二分探索木に最初の値を挿入するときのプログラムの挙動について

rdld036

総合スコア16

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/09/08 07:05

編集2020/09/08 08:45

リンク内容### 前提・実現したいこと

二分探索木T に対し、以下の命令を実行するプログラムを作成してください。

insert k: Tにキー k を挿入する。

という問題なのですが、これをC++で実装するにあたって模範解答を見ると以下のようになってました。しかしこのinsert関数の部分ですが、一番初めにデータを挿入するときrootにどのようにデータが追加されるか理解できません。これだと、xがrootで初期化されていて、whileループに入り、yにxのrootが代入されて, yがNILでなくなってしまうのではないでしょうか。そうなるとif(y == NIL)が偽になってしまい、結局rootが定まらなくなってしまうと思います。もしwhileループを経ないのであれば、どのタイミングでxにNILが代入されるのでしょうか。この点について解説していただけますか。

該当のソースコード

c++

1#include <cstdio> 2#include <cstdlib> 3#include <string> 4#include <iostream> 5 6using namespace std; 7 8struct Node{ 9 int key; 10 Node *right, *left, *parent; 11}; 12 13Node *root, *NIL; 14 15void insert(int k) 16{ 17 Node *y = NIL; 18 Node *x = root; 19 Node *z; 20 21 z = (Node *)malloc(sizeof(Node)); 22 z->key = k; 23 z->left = NIL; 24 z->right = NIL; 25 26 while(x != NIL ){ 27 y = x; 28 if(z->key < x->key){ 29 x = x->left; 30 }else{ 31 x = x->right; 32 } 33 } 34 z->parent = y; 35 if(y == NIL){ 36 root = z; 37 }else { 38 if(z->key < y->key){ 39 y->left = z; 40 }else{ 41 y->right = z; 42 } 43 } 44} 45 46void inorder(Node *u) 47{ 48 if(u == NIL) return; 49 inorder(u->left); 50 printf(" %d", u->key); 51 inorder(u->right); 52} 53 54void preorder(Node *u) 55{ 56 if(u == NIL) return; 57 printf(" %d", u->key); 58 preorder(u->left); 59 preorder(u->right); 60} 61 62int main() 63{ 64 int n, i, x; 65 string com; 66 67 scanf("%d", &n); 68 69 for(i = 0; i < n; i++){ 70 cin >> com; 71 if(com == "insert"){ 72 scanf("%d", &x); 73 insert(x); 74 }else{ 75 inorder(root); 76 printf("\n"); 77 preorder(root); 78 printf("\n"); 79 } 80 } 81 return 0; 82}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mjk

2020/09/08 07:28

何かの「問題」に関する質問には「問題」へのリンクを貼ってください。 コードの書き方について(LouiS0616さん) https://teratail.com/questions/151115 >>teratailには、コードを見やすく表示する機能があります。 >>質問編集画面を開き、コードを選択した状態で<code>ボタンを押してください。
mjk

2020/09/08 08:40

AOJの問題ですよね?引用する場合は「問題」へのリンクを貼ってください。
guest

回答2

0

自己解決

グローバル変数を宣言のみした場合、0に初期化される。一方ローカル変数ではごみ値で初期化される。今回はポインタ変数なのでどちらもnullptrになり、結果最初の時点でx==NILになった。

投稿2020/09/11 04:36

rdld036

総合スコア16

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

これだと、xがrootで初期化されていて、whileループに入り、yにxのrootが代入されて, yがNILでなくなってしまうのではないでしょうか。

模範解答を疑っても仕方ありません。
模範解答が理解出来ない時はデバッグしてみましょう。

1回目のinsert 7の処理ではwhile()ループには入っていません。
何故ならx != NIL がfalse、つまりx == NILだからです。

2回目のinsert 5でやっとwhile()ループに入ります。

C++

1 if (x == NIL) printf("x=NIL1\n"); 2 while (x != NIL) { 3 y = x; 4 if (z->key < x->key) { 5 x = x->left; 6 } else { 7 x = x->right; 8 } 9 } 10 if (x == NIL) printf("x=NIL2\n"); 11

input

13 2insert 7 3insert 5 4print

output

13 2insert 7 3x=NIL1 4x=NIL2 5insert 5 6x=NIL2 7print 8 5 7 9 7 5

もしwhileループを経ないのであれば、どのタイミングでxにNILが代入されるのでしょうか。

xにNILが代入されるというよりも、比較したら値が同じということです。
Node *root, *NIL;
Node *x = root;
つまり全て空っぽのNodeなので比較しても同じということです。

C++

1Node *root, *NIL; 2 3void insert(int k) { 4 Node *y = NIL; 5 Node *x = root; 6 Node *z; 7

投稿2020/09/08 09:10

編集2020/09/08 09:26
mjk

総合スコア303

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rdld036

2020/09/08 09:36 編集

初期化せず宣言だけしたとき、両方のポインタ変数の値はNULLを返すということでしょうか
mjk

2020/09/08 09:38 編集

ポインタの値というよりも、Nodeが空なので比較したら全て同じという結果です。 x==NILなのでwhile (x != NIL) {}ループに入らないというデバッグ結果を見ても納得いかないですか?
mjk

2020/09/08 09:46 編集

cout << root << " " << NIL << endl; これを見たい場所に入れるだけで見れますよね。 それくらい聞く前にご自分でデバッグして出力して試したらどうでしょうか? 私はあなたのテスターではありませんよ。
rdld036

2020/09/08 10:14

おそらくグローバル変数で初期化せず宣言したためにx==NILになったのかと思います。いろいろご指摘していただきありがとうございます。
rdld036

2020/09/11 02:39

私は結果論ではなくそうなる理由を知りたかっただけですので。でも自力で解決したので大丈夫です。質問の仕方については以後気をつけます。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問