二叉排序树删除、搜索、插入的递归实现

  #返回上一级

@Author: 张海拔

@Update: 2014-01-17

@Link: http://www.cnblogs.com/zhanghaiba/p/3524079.html

 

二叉排序树本身就是递归定义的,用递归实现还是挺简单的。迭代实现见 “二叉排序树删除、搜索、插入的迭代实现 link(public)

#插入操作:

若树根为空则返回一个新节点,

否则若item < root->item,则到左子树中去插入;若item > root->item,则到右子树去插入,若item == root->item,则忽略;插入完毕后返回树根。

 

#删除操作:

若树根为空返回NULL,删除过程伴随着搜索,如果找不到待删节点,则搜索到边界(当前树根为空)时,删除空树应该返回NULL。

否则,若item < root->item,则到左子树去删除;若item > root->item,则到右子树去删除;若item == root->item,说明找到了待删除的节点D。

此时有三种情况:

1)若D节点有左孩子

想象D放在BST中序遍历序列(从小到大的序列)中,而D的直接前驱必定是D的左子树里面值最大的那个节点,设为C。

找到C之后,让C和D交换值,此时问题转换为删除C

因为马上要删除C,所以C的值没必要修改。注意C的特征是一定不存在右孩子(左孩子可能存在),这意味这C的直接前驱就是C的左孩子

删除C则递归地删除C的左孩子,左孩子可能是C节点也可能是E节点(见情况2),所以

直到当前C(或当前E)的左(右)孩子为空即C(E)成为叶子,此时删除叶子C(E)则归结为情况3),所以情况3)是递归出口(终止条件)。

2)若D节点没有左孩子但有右孩子,与情况1)的分析是对称的,故略。(设D的直接后继为E

3)若D节点是叶子,则直接删除它。(释放空间并使之指向NULL)

删除完毕后返回树根。

 

#搜索操作:

若树根是空则返回NULL。

若item < root->item,返回搜索左子树的搜索结果;若item > root->item,返回搜索右子树的搜索结果;若item == root->item,则直接返回root。

root是指向关键字节点的指针。显然找不到时(找到边界了),当前树根是空,归结为第一种情况返回NULL。

 

上述实现中——

(1)如果要可视化BST(打印出成一棵树),需要装一个Greg Lee编写的tree模块,主要是用Lex/Flex写成的开源小工具。

Linux用户直接make即可。Mac用户编译时先修改Makefile,把Lex改为Flex,再make即可。

这个模块软件的安装包google搜索"Greg Lee tree"即可找到,用法参见下载页面的说明或源代码中的README。

上述程序中,生成的tree_src.txt与本程序在同一目录,要确保有写、删权限,其次我的tree在~/tree/tree中,所以外部命令调用的是"cat ./tree_src.txt | ~/tree/tree"

fopen要支持覆盖写入比较啰嗦,所以在打开tree_src.txt前先执行强制删除该文件的外部命令(因为如果没有该文件也是不会报错的)。

(2)对于BST:插入操作,如果重复则忽略;删除操作,如果没有该项则也忽略;只有搜索操作做得相对完善。

(3)命令行用户手册:

"i 432" (insert) 即删除值为423的项目(元素), "d 432"(delele) 和 "s 432"(search)类似

"l" (list) 列出BST的中序遍历序列

"p" (print by tree) 使用tree模块可视化/打印出BST

"q" (quit) 退出程序

 

下面是二叉排序树删除、搜索和插入的完整递归实现,以及一个测试示范。

  1 /*
  2  *Author: ZhangHaiba
  3  *Date: 2014-1-16
  4  *File: binary_search_tree_rec.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 recusive
 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 
 30 //public
 31 link NODE(int item, link left, link right); //as constructor
 32 link bst_insert(link root, int item);
 33 link bst_delete(link root, int item);
 34 link bst_search(link root, int item);
 35 void bst_inorder(link root);
 36 void bst_show_by_tree(link root);
 37 //private
 38 link pre(link root);
 39 link next(link root);
 40 void inorder(link root); //included in bst_inorder()
 41 void tree_print(link root, FILE* fd); //included in bst_show_by_tree()
 42 
 43 int main(void)
 44 {
 45 
 46     link r = NULL; //BST root
 47 
 48     //operating this the BST r
 49 
 50             /*** Command Line Manual ***/
 51     /* 
 52      * "i 100" means insert item which value 100
 53      * "d 200" means delete item which value 200
 54      * "s 300" means search item which value 300
 55      * "p" means call the tree module to print the BST tree
 56      * "l" means list the inorder list of BST 
 57      * "q" means quit
 58      */
 59 
 60     while (true) {
 61         char cmd[CMD_LEN];
 62 
 63         scanf("%s", cmd);
 64         if (cmd[0] == 'q')
 65             break;
 66         else if (cmd[0] == 'i' || cmd[0] == 'd' || cmd[0] == 's') {
 67             int item;
 68             scanf("%d", &item);
 69             if (cmd[0] == 'i')
 70                 r = bst_insert(r, item);
 71             else if (cmd[0] == 'd')
 72                 r = bst_delete(r, item);
 73             else {
 74                 link aim_link = bst_search(r, item);
 75                 if (aim_link == NULL)
 76                     printf("Not Found!\n");
 77                 else
 78                     printf("Found: %d\n", aim_link->item);
 79             }
 80         }
 81         else if (cmd[0] == 'p')
 82             bst_show_by_tree(r);
 83         else if (cmd[0] == 'l')
 84             bst_inorder(r);
 85         else
 86             ; //ingnore illegal command line
 87     }
 88     return 0;
 89 }
 90 
 91 link NODE(int item, link left, link right)
 92 {
 93     link born = malloc(sizeof (node));
 94     born->item = item;
 95     born->left = left;
 96     born->right = right;
 97     return born;
 98 }
 99 
100 link bst_insert(link root, int item)
101 {
102     if (root == NULL)
103         return NODE(item, NULL, NULL);
104     else if(item < root->item)
105         root->left = bst_insert(root->left, item);
106     else if(item > root->item)
107         root->right = bst_insert(root->right, item);
108     else
109         ; //ignored the repeating item;
110     return root;
111 }
112 
113 link bst_delete(link root, int item)
114 {
115     if (root == NULL)
116         return NULL;
117     else if (item < root->item)
118         root->left = bst_delete(root->left, item);
119     else if (item > root->item)
120         root->right = bst_delete(root->right, item);
121     else {
122         if (root->left != NULL)
123             root->left = bst_delete(root->left, root->item = pre(root)->item);
124         else if (root->right != NULL)
125             root->right = bst_delete(root->right, root->item = next(root)->item);
126         else {
127             free(root);
128             root = NULL;
129         }
130     }
131     return root;
132 }
133 
134 link bst_search(link root, int item)
135 {
136     if (root == NULL)
137         return NULL;
138     else if (item < root->item)
139         return bst_search(root->left, item);
140     else if (item > root->item)
141         return bst_search(root->right, item);
142     else
143         return root;
144 }
145 
146 //has grantee root != NULL
147 link pre(link root)
148 {
149     link p = root->left;
150 
151     while (p->right != NULL)
152         p = p->right;
153     return p;
154 }
155 
156 //has grantee root != NULL
157 link next(link root)
158 {
159     link p = root->right;
160 
161     while (p->left != NULL)
162         p = p->left;
163     return p;
164 }
165 
166 void bst_inorder(link root)
167 {
168     inorder(root);
169     printf("\n");
170 }
171 
172 void inorder(link root)
173 {
174     if (root == NULL)        
175         return;
176     inorder(root->left);
177     printf("%d ", root->item);
178     inorder(root->right);    
179 }
180 
181 void bst_show_by_tree(link root)
182 {
183     char cmd[CMD_LEN];
184 
185     sprintf(cmd, "rm -f ./tree_src.txt");
186     system(cmd);
187 
188     FILE *fd = fopen("./tree_src.txt", "a+");
189     fprintf(fd, "\n\t\\tree");
190     tree_print(root, fd);
191     fprintf(fd, "\n\n");
192     fclose(fd);
193 
194     sprintf(cmd, "cat ./tree_src.txt | ~/tree/tree");
195     system(cmd);
196 }
197 
198 void tree_print(link root, FILE *fd)
199 {    
200     fprintf(fd, "(");
201     if (root != NULL) {
202         fprintf(fd, "%d", root->item);
203         tree_print(root->left, fd);
204         tree_print(root->right, fd);
205     }
206     fprintf(fd, ")");
207 }

 

测试示范

ZhangHaiba-MacBook-Pro:code apple$ ./a.out
i 432
p

        432
        _|__
        |  |

i 234 i 526
p

           432
         ___|___
         |     |
        234   526
        _|__  _|__
        |  |  |  |

i 43 i 632 i 535 i 333 i 13 i 53 i 35
l
13 35 43 53 234 333 432 526 535 632 
p

                  432
               ____|____
               |       |
              234     526
            ___|____  _|__
            |      |  |  |
            43    333   632
         ___|___  _|__  _|__
         |     |  |  |  |  |
         13    53      535
        _|__  _|__     _|__
        |  |  |  |     |  |
           35
          _|__
          |  |

d 35
p

                  432
               ____|____
               |       |
              234     526
            ___|____  _|__
            |      |  |  |
            43    333   632
         ___|___  _|__  _|__
         |     |  |  |  |  |
         13    53      535
        _|__  _|__     _|__
        |  |  |  |     |  |

d 634
p

                  432
               ____|____
               |       |
              234     526
            ___|____  _|__
            |      |  |  |
            43    333   632
         ___|___  _|__  _|__
         |     |  |  |  |  |
         13    53      535
        _|__  _|__     _|__
        |  |  |  |     |  |

l
13 43 53 234 333 432 526 535 632 
d 432 
p

               333
             ___|____
             |      |
            234    526
            _|__  __|__
            |  |  |   |
            43       632
         ___|___     _|__
         |     |     |  |
         13    53   535
        _|__  _|__  _|__
        |  |  |  |  |  |

d 234
p

             333
           ___|___
           |     |
           53   526
          _|__  _|__
          |  |  |  |
          43      632
         _|__     _|__
         |  |     |  |
         13      535
        _|__     _|__
        |  |     |  |

s 33
Not Found!
s 13
Found: 13
s 526
Found: 526
s 334
Not Found!
i 444
p

              333
           ____|____
           |       |
           53     526
          _|__  ___|___
          |  |  |     |
          43   444   632
         _|__  _|__  _|__
         |  |  |  |  |  |
         13         535
        _|__        _|__
        |  |        |  |

d 53
l
13 43 333 444 526 535 632 
p

             333
          ____|____
          |       |
          43     526
         _|__  ___|___
         |  |  |     |
         13   444   632
        _|__  _|__  _|__
        |  |  |  |  |  |
                   535
                   _|__
                   |  |

d 632
p

             333
          ____|____
          |       |
          43     526
         _|__  ___|___
         |  |  |     |
         13   444   535
        _|__  _|__  _|__
        |  |  |  |  |  |

q

 

  #返回上一级

posted @ 2014-01-17 15:08  张海拔  阅读(1289)  评论(0编辑  收藏  举报