@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! "); 77 else 78 printf("Found: %d ", 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(" "); 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, " \tree"); 190 tree_print(root, fd); 191 fprintf(fd, " "); 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