━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
課題1 (2分木のデータ構造)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
●準備

次のファイルを,ディレクトリ ~/AdvProg/T6/ に保存しておく.

        tree.h
                        2分木のデータと基本関数のためのヘッダ
        tree.c
                        2分木の基本関数
        ex1.c
                        課題1解答用ひな型
        Makefile
                        自動コンパイル用

予習時に上記のソースファイルと以下の課題を熟読し,疑問点を明らかにしておく.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

●課題一覧

基本課題
        1a      2分木データの生成と表示
        1b      2分木を扱う再帰関数の作成
        1c      2分木のデータ構造の理解

発展課題
        1d      2分木に関する判定
        1e      2分木の加工

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

●基本課題 1a (2分木データの生成と表示)

2分木の節を格納するためのデータ構造 (Tree 型) が,2分木のデータと基本関数の
ヘッダファイル tree.h で,次のように定義されている.

        typedef struct _tree {
          char           node;          /* 節のデータ (1文字) */
          struct _tree  *left;          /* 左の子へのポインタ */
          struct _tree  *right;         /* 右の子へのポインタ */
        } Tree;

        

2分木の枝と葉のデータを生成するための二つの関数 branch() と leaf() を作れ.
2分木の基本関数のプログラムファイル tree.c にある定義を,以下の説明に沿って
完成させること.

        Tree *branch(char x, Tree *l, Tree *r);
                ・節 (Tree 型の構造体) を格納する記憶領域を確保
                ・節を初期化 (節データを x,左右の子へのポインタを l, r に設定)
                ・生成した Tree 型の構造体へのポインタを戻り値として返却

        

        Tree *leaf(char x);
                ・節 (Tree 型の構造体) を格納する記憶領域を確保
                ・節を初期化 (節データを x,左右の子へのポインタを NULL に設定)
                ・生成した Tree 型の構造体へのポインタを戻り値として返却

        

これ以降の課題の答えは,課題1のソースファイル ex1.c に書き込む.

関数 branch() と leaf() を使って,算術式を表す2分木のデータを生成し,
各2分木の根へのポインタを,Tree * 型の変数に格納せよ.

例えば,算術式

        0
        a + b
        (x + (y + 1)) * z

を表すデータを作るなら,それぞれ,次の図の2分木を生成する.

            
        
ファイル tree.c で定義された関数 show_tree() の処理内容を理解した上で,
この関数を使って2分木を表示し,意図通りのデータができていることを確かめよ.

補足

●基本課題 1b (2分木を扱う再帰関数の作成)

2分木の高さを求める関数 height() を作れ.
ここでの木の高さは,根から葉へたどるときに通る頂点数の最大値,と定義する.
例えば,課題 1a の三つの2分木の高さは,それぞれ 1, 2, 4 である.

十分な数の検査データを作り,動作の正しさを確かめよ.

補足

●基本課題 1c (2分木のデータ構造の理解)

まず,次の2分木のデータを生成するプログラムを作る.

        
        
        Tree *t1, *t2, *t3;
        t1 = leaf('a');
        t2 = branch('+', leaf('1'), leaf('b'));
        t3 = branch('*', t1, t2);

2分木の節の内容を詳細表示する関数 show_node() を使って,
t1, t2, t3 が指す節が記憶領域上でどのように格納されるかを調べよ.

また,Tree 型 (つまり struct _tree 型) と,その構成要素である
char 型,Tree * 型,それぞれの型のデータの記憶に必要なバイト数を,
sizeof(Tree), sizeof(char), sizeof(Tree *),の値を表示して調べよ.

この実行結果をもとに (必要なら他の追加実験をして),
2分木全体が記憶領域上でどのように格納されるかを説明 (図解) せよ.

補足

──────────────────────────────────────

●発展課題 1d (2分木に関する判定)

与えられた2分木が左右対称かどうかを判定する関数 is_symmetric() を作れ.

例えば,算術式 x や (y + 1) * (1 + y) を表す木

          
        
は対称的だが,a * 1 や (a * 1) + (1 + a) を表す木

          
        
は対称的ではない.

補足

●発展課題 1e (2分木の加工)

2分木を左右反転した鏡像を求める関数 mirror() を作れ.

例えば,(a * b) * (1 + x) の2分木に対して (x + 1) * (b * a) の2分木
が得られればよい (下図).

         → 
        
補足

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
演習のホームページ

山田 俊行
https://www.cs.info.mie-u.ac.jp/~toshi/