このツリー構造を使うためには,型宣言として以下のものが必ず必要である.
リスト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 |
著作者 | 紀平拓男・春日伸弥 |
出版社 | ソフトバンク パブリッシング株式会社 |