#返回上一級
html
@Author: 張海拔node
@Update: 2014-01-17app
@Link: http://www.cnblogs.com/zhanghaiba/p/3524079.html工具
二叉排序樹自己就是遞歸定義的,用遞歸實現仍是挺簡單的。迭代實現見 「二叉排序樹刪除、搜索、插入的迭代實現 link(public)」測試
#插入操做:ui
若樹根爲空則返回一個新節點,this
不然若item < root->item,則到左子樹中去插入;若item > root->item,則到右子樹去插入,若item == root->item,則忽略;插入完畢後返回樹根。google
#刪除操做:spa
若樹根爲空返回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