二叉の並べ替えツリーの削除、検索、挿入の繰り返しが実現されます.


同前
@Author:張海抜
@Update:2014-01-24
@Link: http://www.cnblogs.com/zhanghaiba/p/3532885.html
 
反復実装の難しさは削除操作です.
難点1は、様々な状況における削除(論理的難点)を明確にしたい場合であり、難点2は反復実施中の削除操作において、一般的にポインタに関するポインタ(C言語実現困難点)である.
難点1解答――
削除に伴う検索プロセスは、削除すべき点が見つからない場合は操作を無視し、削除すべきノードDが見つかったら、3つの状況に分けられる.
1)Dに左の子供がいるなら、BSTシーケンス(中のシーケンス:小さいから大きいまで)では、Dは少なくとも直接の前駆ノードCが存在し、Cは必ずDノードの左のサブツリーの中の値が一番大きいノードであると説明する.
「直接」という条件を満たすためには、CはDの左側に近いので、CはDノードの左サブツリーの最大ノードであることが必要である.
左の子の木もBSTで、左の子の木の自身が右の子供がないならば木の根は最大です.左の子の木の一番右の子が一番大きいです.
言い換えれば、CはDの左の子供かDの左の子供の右の子供です.(右の子供がいないのがCの特徴です.さもなければ最大ではないです.)
Cを指すポインタが得られ、DにCの値が割り当てられます.配列[2,3,5,7,9,11,13]のように[2,3,5,5,9,11,13]が[D=7]に変化します.
この時、CとDの両方の結点交換位置があると考えられます.(Cを削除してもBSTです.)ので、問題は削除Dから削除Cに変換されます.(Cは固定的な特徴があるので)
私たちはCを指すポインタqを持っていますが、Cの特徴は右の子供がいない(左の子供がいるとは限らない)ことです.Cの直接の先駆者はその左の子供です.
したがって、残りの作業は、Cを指していたポインタqをCの左の子供に向け、Cノードメモリを解放することである.
2)Dが左の子供がいないが、右の子供がいる場合、BST順序では、Dは直接的な後継ノードEが存在し、Eは必ずDノードの右のサブツリーの中の最小ノードであると説明する.
次の解析は1)の解析と対称である.
3)Dが葉っぱであれば、Dを直接削除し、Dを指すポインタをNULLにセットします.
 
難点2解答――
ポインタの針を使わないとき、ポインタpを削除すべき点Dに向けます.このpはDの親ノードのnextポインタのコピーにすぎません.
Dノードを解放するためには問題はないが、pをNULLにセットし、Dの親ノードのnextをNULLにセットしていない.
これは、葉を削除するという簡単な状況では、ほぼ間違いが発生します(不正メモリにアクセスしました).
ですから、まずrootを保存してください.link*p=&rootを設定して、常にポインタの針を保存します.
C(本当に削除するノード)を見つけた時(Cが満たす条件は(*p)->right==NULL)、*pがCの親ノードのnextです.これで正しい修正ができます.
また、BSTの最後のノードが削除された後に、まだrootであればエラーが発生します.rootと**pはノードメモリを共有しています.
この場合は、*pだけでなくNULLに置く必要があります.rootもNULLにするので、コードを追加します.
 
言及に値するのは、
ここでは、「二叉並べ替えツリーの削除、検索、挿入の再帰的な実現」を繰り返します.  link(public) ",削除操作は正しいですが、具体的には違いがあります.
下の木を見て、50のノードを削除するとき――
             50

          ___|___

          |     |

          38    65

         _|__  _|__

         |  |  |  |

         35       70

        _|__     _|__

        |  |     |  |

           36    68

          _|__  _|__

          |  |  |  |

                67

               _|__

               |  |





/*    50  BST*/



             38

          ___|___

          |     |

          36    65

         _|__  _|__

         |  |  |  |

         35       70

        _|__     _|__

        |  |     |  |

                 68

                _|__

                |  |

                67

               _|__

               |  |





/*    50  BST*/



            38

         ___|___

         |     |

         35    65

        _|__  _|__

        |  |  |  |

           36    70

          _|__  _|__

          |  |  |  |

                68

               _|__

               |  |

               67

              _|__

              |  |
 
再帰的に実現すると、50を削除すると38(50は38になる)を再帰的に削除し、38を削除して再帰的に36を削除する(38は36になる).最後に36の葉を削除することにまとめる(元の36).
反復実装では、50を削除すると38は50に割り当てられ、38(元の38)を直接削除し、38を指すポインタ(ルートノードのnextポインタ)を元の38ノードを指す左の子供に変更します.
 
次の二叉の順序付けツリーの完全な反復実装と削除状況が十分に多いテストの例示.
  1 /*

  2  *Author: ZhangHaiba

  3  *Date: 2014-1-24

  4  *File: binary_search_tree_iter.c

  5  *

  6  *this demo shows how to build a BST data structure

  7  *and support some command line to operate this BST 

  8  *such like i(insert), d(delete), s(search), q(quit) etc

  9  *interestingly, this demo use tree module which written by Greg Lee

 10  *making BST data structure and it's opreation visualization

 11  *

 12  *hint: implementation iterative

 13  */

 14 

 15 #include <stdio.h>

 16 #include <stdlib.h>

 17 #include <stdbool.h>

 18 #define MOD 256

 19 #define CMD_LEN 128

 20 

 21 typedef struct node* link;

 22 

 23 typedef struct node {

 24     int item;

 25     link left;

 26     link right;

 27 }node;

 28 

 29 //public

 30 link NODE(int item, link left, link right); //as constructor

 31 link bst_insert(link root, int item);

 32 link bst_delete(link root, int item);

 33 link bst_search(link root, int item);

 34 void bst_inorder(link root);

 35 void bst_show_by_tree(link root);

 36 //private

 37 link* pre(link root);

 38 link* next(link root);

 39 void inorder(link root); //included in bst_inorder()

 40 void tree_print(link root, FILE* fd); //included in bst_show_by_tree()

 41 

 42 int main(void)

 43 {

 44 

 45     link r = NULL; //BST root

 46 

 47     //operating this the BST r

 48 

 49             /*** Command Line Manual ***/

 50     /* 

 51      * "i 100" means insert item which value 100

 52      * "d 200" means delete item which value 200

 53      * "s 300" means search item which value 300

 54      * "p" means call the tree module to print the BST tree

 55      * "l" means list the inorder list of BST 

 56      * "q" means quit

 57      */

 58 

 59     while (true) {

 60         char cmd[CMD_LEN];

 61 

 62         scanf("%s", cmd);

 63         if (cmd[0] == 'q')

 64             break;

 65         else if (cmd[0] == 'i' || cmd[0] == 'd' || cmd[0] == 's') {

 66             int item;

 67             scanf("%d", &item);

 68             if (cmd[0] == 'i')

 69                 r = bst_insert(r, item);

 70             else if (cmd[0] == 'd')

 71                 r = bst_delete(r, item);

 72             else {

 73                 link aim_link = bst_search(r, item);

 74                 if (aim_link == NULL)

 75                     printf("Not Found!
"); 76 else 77 printf("Found: %d
", aim_link->item); 78 } 79 } 80 else if (cmd[0] == 'p') 81 bst_show_by_tree(r); 82 else if (cmd[0] == 'l') 83 bst_inorder(r); 84 else 85 ; //ingnore illegal command line 86 } 87 return 0; 88 } 89 90 link NODE(int item, link left, link right) 91 { 92 link born = malloc(sizeof (node)); 93 born->item = item; 94 born->left = left; 95 born->right = right; 96 return born; 97 } 98 99 link bst_insert(link root, int item) 100 { 101 if (root == NULL) 102 return NODE(item, NULL, NULL); 103 link p = root; 104 while (true) { 105 if (item < p->item) { 106 if (p->left != NULL) 107 p = p->left; 108 else { 109 p->left = NODE(item, NULL, NULL); 110 return root; 111 } 112 } else if (item > p->item) { 113 if (p->right != NULL) 114 p = p->right; 115 else { 116 p->right = NODE(item, NULL, NULL); 117 return root; 118 } 119 } else 120 return root; 121 } 122 } 123 124 link bst_delete(link root, int item) 125 { 126 if (root == NULL) 127 return NULL; 128 link save = root; 129 link *p = &root; 130 while (true) { 131 if (item < (*p)->item) { 132 if ((*p)->left != NULL) 133 p = &((*p)->left); 134 else 135 return save; //if search failed then delete nothing 136 } else if (item > (*p)->item) { 137 if ((*p)->right != NULL) 138 p = &((*p)->right); 139 else 140 return save; 141 } else { 142 if ((*p)->left != NULL) { 143 link *q = pre(*p); 144 (*p)->item = (*q)->item; 145 link del = *q; 146 *q = (*q)->left; 147 free(del); 148 } else if ((*p)->right != NULL) { 149 link *q = next(*p); 150 (*p)->item = (*q)->item; 151 link del = *q; 152 *q = (*q)->right; 153 free(del); 154 } else { 155 free(*p); 156 if (*p == save) //guarantee delete correctly in case: BST those have only one node 157 save = NULL; 158 *p = NULL; 159 } 160 return save; 161 } 162 } 163 } 164 165 link bst_search(link root, int item) 166 { 167 if (root == NULL) 168 return NULL; 169 link p = root; 170 while (true) { 171 if (item < p->item) { 172 if (p->left != NULL) 173 p = p->left; 174 else 175 return NULL; 176 } else if (item > p->item) { 177 if (p->right != NULL) 178 p = p->right; 179 else 180 return NULL; 181 } else 182 return p; 183 } 184 } 185 186 //guarantee root != NULL 187 link* pre(link root) 188 { 189 link *p = &(root->left); 190 191 while ((*p)->right != NULL) 192 p = &((*p)->right); 193 return p; 194 } 195 196 //guarantee root != NULL 197 link* next(link root) 198 { 199 link *p = &(root->right); 200 201 while ((*p)->left != NULL) 202 p = &((*p)->left); 203 return p; 204 } 205 206 void bst_inorder(link root) 207 { 208 inorder(root); 209 printf("
"); 210 } 211 212 void inorder(link root) 213 { 214 if (root == NULL) 215 return; 216 inorder(root->left); 217 printf("%d ", root->item); 218 inorder(root->right); 219 } 220 221 void bst_show_by_tree(link root) 222 { 223 char cmd[CMD_LEN]; 224 225 sprintf(cmd, "rm -f ./tree_src.txt"); 226 system(cmd); 227 228 FILE *fd = fopen("./tree_src.txt", "a+"); 229 fprintf(fd, "
\t\\tree
"); 230 tree_print(root, fd); 231 fprintf(fd, "

"); 232 fclose(fd); 233 234 sprintf(cmd, "cat ./tree_src.txt | ~/tree/tree"); 235 system(cmd); 236 } 237 238 void tree_print(link root, FILE *fd) 239 { 240 fprintf(fd, "("); 241 if (root != NULL) { 242 fprintf(fd, "%d", root->item); 243 tree_print(root->left, fd); 244 tree_print(root->right, fd); 245 } 246 fprintf(fd, ")"); 247 }
 
テストのモデル:
ZhangHaiba-MacBook-Pro:code apple$ ./a.out

p



    



i 50

p



         50

        _|__

        |  |



i 45 i 55

p



            50

         ___|___

         |     |

         45    55

        _|__  _|__

        |  |  |  |



i 35 i 36 i 39 i 38

l

35 36 38 39 45 50 55 

i 70 i 68 i 61 i 65 i 62 i 67

p



              50

          ____|____

          |       |

          45      55

         _|__   __|___

         |  |   |    |

         35          70

        _|__        _|__

        |  |        |  |

           36       68

          _|__     _|__

          |  |     |  |

             39    61

            _|__  _|__

            |  |  |  |

            38       65

           _|__   ___|___

           |  |   |     |

                  62    67

                 _|__  _|__

                 |  |  |  |



l

35 36 38 39 45 50 55 61 62 65 67 68 70 

s 66

Not Found!

s 62

Found: 62

s 39

Found: 39

s 37

Not Found!

d 62

p



              50

          ____|____

          |       |

          45      55

         _|__   __|___

         |  |   |    |

         35          70

        _|__        _|__

        |  |        |  |

           36       68

          _|__     _|__

          |  |     |  |

             39    61

            _|__  _|__

            |  |  |  |

            38       65

           _|__     _|__

           |  |     |  |

                       67

                      _|__

                      |  |



d 45

p



              50

          ____|____

          |       |

          39      55

         _|__   __|___

         |  |   |    |

         35          70

        _|__        _|__

        |  |        |  |

           36       68

          _|__     _|__

          |  |     |  |

             38    61

            _|__  _|__

            |  |  |  |

                     65

                    _|__

                    |  |

                       67

                      _|__

                      |  |



d 55

p



              50

          ____|____

          |       |

          39      61

         _|__   __|___

         |  |   |    |

         35          70

        _|__        _|__

        |  |        |  |

           36       68

          _|__     _|__

          |  |     |  |

             38    65

            _|__  _|__

            |  |  |  |

                     67

                    _|__

                    |  |



d 39

p



             50

          ___|___

          |     |

          38    61

         _|__  _|__

         |  |  |  |

         35       70

        _|__     _|__

        |  |     |  |

           36    68

          _|__  _|__

          |  |  |  |

                65

               _|__

               |  |

                  67

                 _|__

                 |  |



d 61

p



             50

          ___|___

          |     |

          38    65

         _|__  _|__

         |  |  |  |

         35       70

        _|__     _|__

        |  |     |  |

           36    68

          _|__  _|__

          |  |  |  |

                67

               _|__

               |  |



d 50

p



            38

         ___|___

         |     |

         35    65

        _|__  _|__

        |  |  |  |

           36    70

          _|__  _|__

          |  |  |  |

                68

               _|__

               |  |

               67

              _|__

              |  |



d 38 d 68 d 70 d 35 d 36 d 67   

p



         65

        _|__

        |  |



d 65

p



    



i 99

p



         99

        _|__

        |  |



q
 
  同前