このツリー構造を使うためには,型宣言として以下のものが必ず必要である.
リスト1 2分木を表す構 造体.教科書のList 6-1(転載について)
1 typedef struct _tag_tree_node
2 {
3 /* このノードが保持する値 */
4 int value;
5 /* 自分より小さい値のnode:図では左側のノード */
6 struct _tag_tree_node *left;
7 /* 自分より大きい値のnode:図では右側のノード */
8 struct _tag_tree_node *right;
9 } tree_node;
ツリーはノードのみならず,ルートを表すポインターが必要である.教科書のList
6-4(p.176)のように,tree_node *tree_root=NULL;
リスト2 2分 木のノードの作成.教科書List 6-2の一部(転載について)
1 tree_node* create_new_node(int num)
2 {
3 tree_node *tree_new;
4
5 /* 新しいnodeを作成して,初期化する */
6 tree_new=(tree_node*)malloc(sizeof(tree_node));
7 if(tree_new==NULL)
8 exit(EXIT_FAILURE);
9 tree_new->left=NULL;
10 tree_new->right=NULL;
11 tree_new->value=num;
12
13 return tree_new;
14 }
リスト3の動作は,以下の通りである.
リスト3 2分木のノードの追加.教科書List 6-2の一部(転載について)
1 void insert_tree(int num,tree_node *node)
2 {
3 /* 1つも挿入されていない場合 */
4 if(node==NULL)
5 {
6 tree_root=create_new_node(num);
7 return;
8 }
9
10 /* numが現在のnodeの値よりも小さい場合 */
11 if(node->value>num)
12 {
13 if(node->left!=NULL)
14 insert_tree(num,node->left);
15 else
16 /* 左側に追加する */
17 node->left=create_new_node(num);
18 }
19 else
20 /* numが現在のnodeの値以上の場合 */
21 {
22 if(node->right!=NULL)
23 insert_tree(num,node->right);
24 else
25 /* 右側に追加する */
26 node->right=create_new_node(num);
27 }
28
29 return;
30 }
リスト4の動作は,以下の通りである.要するにルートから,大小 関係を調べて,ツリーをたどって探索をしているのである.
リスト4 2分木のサーチ. 教科書List 6-3(転載について)
1 tree_node* find_value(tree_node* node,int val)
2 /* 発見したtree_nodeのポインタを返す。ない場合はNULL */
3 {
4 /* 自分より小さい値ならば,左側 */
5 if(node->value>val)
6 {
7 if(node->left==NULL) /* もし左側になければ,valはない */
8 return NULL;
9 return find_value(node->left,val);
10 }
11 /* 自分より大きい値ならば,右側 */
12 if(node->value<val)
13 {
14 if(node->right==NULL)
15 return NULL; /* もし右側になければ,valはない */
16 return find_value(node->right,val);
17 }
18
19 /* 見つかれば,見つかった値を返す */
20 return node;
21 }
この関数の動作に先立って,使われている変数の役割を示しておく.
|
リスト4の動作は,以下の通りである.
リスト5 2分木の削 除.教科書List6-4の一部(転載について)
1 int delete_tree(int val)
2 /* valを削除する。成功すれば1,失敗すれば0を返す */
3 {
4 tree_node *node,*parent_node;
5 tree_node *left_biggest;
6 int direction;
7 node=tree_root;
8 parent_node=NULL;
9 direction=0;
10
11 /* while文で削除すべき対象を見つける(find_valueと同じ) */
12 while(node!=NULL&&node->value!=val)
13 {
14 if(node->value>val)
15 {
16 parent_node=node;
17 node=node->left;
18 direction=-1; /* 親の左側 */
19 }
20 else
21 {
22 parent_node=node;
23 node=node->right;
24 direction=1; /* 親の右側 */
25 }
26 }
27 if(node==NULL) /* 見つからなかった */
28 return 0;
29
30 if(node->left==NULL||node->right==NULL)
31 {
32 /* 左か右,どちらかがNULLであった場合
33 (両方NULLの場合も含む) */
34 if(node->left==NULL)
35 {
36 /* 親のポインタを変更する */
37 if(direction==-1)
38 parent_node->left=node->right;
39 if(direction==1)
40 parent_node->right=node->right;
41 if(direction==0)
42 tree_root=node->right;
43 }
44 else
45 {
46 /* 親のポインタを変更する */
47 if(direction==-1)
48 parent_node->left=node->left;
49 if(direction==1)
50 parent_node->right=node->left;
51 if(direction==0)
52 tree_root=node->left;
53 }
54
55 free(node);
56 }
57 else
58 {
59 /* 両者ともNULLでなかった場合 */
60
61 /* nodeの左側の最も大きな値(最も右側の値)を取得する */
62 left_biggest=node->left;
63 parent_node=node;
64 direction=-1;
65 while(left_biggest->right!=NULL)
66 {
67 parent_node=left_biggest;
68 left_biggest=left_biggest->right;
69 direction=1;
70 }
71
72 /* left_biggestの値をnodeに代入し,
73 left_biggestは左側の枝を入れる */
74 node->value=left_biggest->value;
75 if(direction==-1)
76 parent_node->left=left_biggest->left;
77 else
78 parent_node->right=left_biggest->left;
79 free(left_biggest);
80 }
81
82 return 1;
83 }
リスト6 メモリー の解放.教科書List6-4の一部(転載について)
1 void free_tree(tree_node* node)
2 {
3 if(node==NULL)
4 return;
5 /* まず子nodeのメモリを解放する */
6 free_tree(node->left);
7 free_tree(node->right);
8 /* 自分自身を解放 */
9 free(node);
10 }
[転載について]
このページ中のリスト1とリスト2,リスト3,リスト4,リスト5,リスト6のプログラムは,教科書として使用している以下の書籍
| 書名 | プログラミングの宝箱 アルゴリズムとデータ構造 ISBN4-7973-2419-8 |
| 著作者 | 紀平拓男・春日伸弥 |
| 出版社 | ソフトバンク パブリッシング株式会社 |