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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

Q&A

解決済

2回答

1878閲覧

C言語で2分木構造の実装

Mellonn

総合スコア3

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

0グッド

0クリップ

投稿2021/11/13 05:12

編集2021/11/13 06:04

![イメージ説明]ttps://www.google.com/url?sa=i&url=https%3A%2F%2Fwww.momoyama-usagi.com%2Fentry%2Finfo-algo-tree-traverse&psig=AOvVaw3AGtH1evbZaou6u2ksi6St&ust=1636866178615000&source=images&cd=vfe&ved=0CAsQjRxqFwoTCLDrpvjHlPQCFQAAAAAdAAAAABAI

例えばこのような2分木であるとしたら,

15(10(4(NULL,NULL),14(12(NULL,NULL),NULL)),19(17(NULL,NULL),NULL))

と出力するプログラムを実装しようとしています.

引数はNode型のnです.

Node型は

c

1typedef struct node { 2 char *label; 3 struct node *left; 4 struct node *right; 5} Node;

と定義してあります。

再帰関数で実装できそうだなというところまでしか思いつかず,うまくいきません。

実装の考え方を教えて頂きたいです。よろしくお願いします。

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

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

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

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

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

yu-ima

2021/11/13 05:43

4を4(NULL,NULL)と表現するのであれば、12,17でも12(NULL,NILL), 17(NULL,NULL)では ないですか?
jimbe

2021/11/13 05:50 編集

リンク先に考え方やコードが載っていますが、それを実装・実行してみたりはしていないのでしょうか。
Mellonn

2021/11/13 06:07

yu-imaさん,修正しました jimbeさん,別のところでリンク先のコードを参考にしました。今回の質問内容である2分木の構造の実装に関しては記載がないです。
jimbe

2021/11/13 07:24

> 今回の質問内容である2分木の構造の実装に関しては記載がない。 つまり問題は、2分木による "表示" では無く、2分木の生成自体ということでしょうか。
Mellonn

2021/11/13 07:28

2分木の生成自体はできています。(私の1つ前の質問を見ていただければわかります) 生成したNode型で構成されている2分木を本質問に記載しているような出力のように表示させたいのが現状です。
jimbe

2021/11/13 07:33

であれば、リンク先の情報・コードで十分対応できると思うのですが、どこが分からないのでしょうか。
Mellonn

2021/11/13 07:50

https://www.momoyama-usagi.com/entry/info-algo-tree-traverse 私はこのリンクの内容を本質問内容へと昇華できませんでした。単純にノードのlabelを出力するだけであればよいのですが,ノードとその子のノードも合わせてとなると,リンク先の実装に比べると複雑になると自分は感じました。
Mellonn

2021/11/13 07:51

もう少しリンクの内容を落とし込んで考えてみます。
jimbe

2021/11/13 08:51 編集

>単純にノードのlabelを出力するだけであればよいのですが,ノードとその子のノードも合わせてとなると ~ 難しく考えすぎのように思います。 ツリーが再帰関数で処理できるのは、ツリーを構成する各部分がツリーだからです。 まずはツリーにデータが1つもない場合(=ルートが null の場合)にどう表示されるべきかを考え、それを実装してそのように表示されることを確認してください。 次にデータが1つ(例でいえば "15" )を入れ、どう表示されるべきかを考え、それを実装してそのように表示されることを確認してください。そして同時に、先の「データが1つもない場合」のツリー構造に戻してもコードを直さずに先の結果と同じく表示されることを確認してください。 これだけでもほぼ形は出来ていることと思います。
guest

回答2

0

ベストアンサー

まずは再帰を考えず、データが無いツリーを表示すると考えてみます。

ご提示されている例にはありませんが、恐らく "NULL" とだけ表示されることでしょう。
つまり(関数名はテキトウです)

c

1 void printTree(Node *n) { 2 printf("NULL"); 3 }

これだけです。

次に "15" だけが入ったツリーとしましょう。
先の root=NULL を壊さずに実装するとして、

c

1 void printTree(Node *n) { 2 if(n == NULL) { 3 printf("NULL"); 4 } else { 5 printf("15(NULL,NULL)"); 6 } 7 }

が一番簡単でしょうか。ズルイ? でも、結果は想定通りです。
このコードから始めます。

もちろんこのままでは実際のデータに関係無く "15" や "NULL" になってしまいますので、表示の各部分を置き換えていきます。

まず、 else の表示部分を固定部分と可変部分に分けます。
(以降、else の中だけ表記します。)

c

1 printf("15"); //可変 2 printf("("); //固定 3 printf("NULL"); //可変 4 printf(","); //固定 5 printf("NULL"); //可変 6 printf(")"); //固定

"15" は引数 n からの label に入っていますので置き換えます。

c

1 printf(n->label); 2 printf("("); 3 printf("NULL"); 4 printf(","); 5 printf("NULL"); 6 printf(")");

最初の "NULL" は同じく n からの left の値で、その次は right です。

c

1 printf(n->label); 2 printf("("); 3 if(n->left == NULL) { 4 printf("NULL"); 5 } 6 printf(","); 7 if(n->right == NULL) { 8 printf("NULL"); 9 } 10 printf(")");

・・・これでは left も right もそれぞれ NULL じゃない場合に何も出力されません。
では、例えば left が NULL では無い場合、何を表示するのでしょうか。

"left をルートとしたツリー" を表示すれば良いはずです。
恐らくはココが一番のキモと思います。

ここで、「ツリーの一部はまたツリー」を処理する為に再帰を使うことになります。

c

1 printf(n->label); 2 printf("("); 3 if(n->left == NULL) { 4 printf("NULL"); 5 } else { 6 printTree(n->left); 7 } 8 printf(","); 9 if(n->right == NULL) { 10 printf("NULL"); 11 } else { 12 printTree(n->right); 13 } 14 printf(")");

これで完成・・・ではあるのですが、コードを注意してみると、left や right が NULL の場合の処理は printTree に既に「if(n == NULL) {}」としてあります。
ですのでそれぞれの if 文は省くことが出来ます。(関数全体を表記します。)

c

1 void printTree(Node *n) { 2 if(n == NULL) { 3 printf("NULL"); 4 } else { 5 printf(n->label); 6 printf("("); 7 printTree(n->left); 8 printf(","); 9 printTree(n->right); 10 printf(")"); 11 } 12 }

もし left が NULL だったら、一番上の "n == NULL" に引っかかって "NULL" が表示されるはずで、 NULL で無かったら else に入って label 等が表示されるはずです。

時には全体(構造)を見("ツリー")、時には目の前のコードだけに集中("printf の分解")してみたりという臨機応変(?)な視点から考えるのも、必要になるかと思います。

投稿2021/11/13 09:29

編集2021/11/13 09:59
jimbe

総合スコア12646

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

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

Mellonn

2021/11/13 11:02

懇切丁寧に解説してくださり,ありがとうございます! 簡単な具体例から考えて抽象化するという方法は今までできていなかったのでとても参考になりました。 求めている結果を分割するという手法も今後取り入れていこうと思います。
guest

0

自分自身を再起関数として機能させます。

1.  ノードがnullであれば、"NULL"を出力し復帰する。
2. nullでなければ、labelと、"("を出力する。
3. 左ノードを持って自分自身を呼び出す。
4. "," を出力
5. 右ノードを持って自分自身を呼び出す。
6. ")"
7. 復帰

以上でどうでしょう。

投稿2021/11/13 07:46

yu-ima

総合スコア249

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

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

Mellonn

2021/11/13 11:03

ありがとうございます!プログラムの概要がつかめた気がします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問