二叉排序树删除、搜索、插入的递归实现
2014-01-17 15:08
555 查看
#返回上一级
@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) 退出程序
下面是二叉排序树删除、搜索和插入的完整递归实现,以及一个测试示范。
测试示范
#返回上一级
@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) 退出程序
下面是二叉排序树删除、搜索和插入的完整递归实现,以及一个测试示范。
/* *Author: ZhangHaiba *Date: 2014-1-16 *File: binary_search_tree_rec.c * *this demo shows how to build a BST data structure *and support some command line to operate this BST *such like i(insert), d(delete), s(search), q(quit) etc *interestingly, this demo use tree module which written by Greg Lee *making BST data structure and it's opreation visualization * *hint: implementation recusive */ #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define MOD 256 #define CMD_LEN 128 typedef struct node* link; typedef struct node { int item; link left; link right; }node; //public link NODE(int item, link left, link right); //as constructor link bst_insert(link root, int item); link bst_delete(link root, int item); link bst_search(link root, int item); void bst_inorder(link root); void bst_show_by_tree(link root); //private link pre(link root); link next(link root); void inorder(link root); //included in bst_inorder() void tree_print(link root, FILE* fd); //included in bst_show_by_tree() int main(void) { link r = NULL; //BST root //operating this the BST r /*** Command Line Manual ***/ /* * "i 100" means insert item which value 100 * "d 200" means delete item which value 200 * "s 300" means search item which value 300 * "p" means call the tree module to print the BST tree * "l" means list the inorder list of BST * "q" means quit */ while (true) { char cmd[CMD_LEN]; scanf("%s", cmd); if (cmd[0] == 'q') break; else if (cmd[0] == 'i' || cmd[0] == 'd' || cmd[0] == 's') { int item; scanf("%d", &item); if (cmd[0] == 'i') r = bst_insert(r, item); else if (cmd[0] == 'd') r = bst_delete(r, item); else { link aim_link = bst_search(r, item); if (aim_link == NULL) printf("Not Found!\n"); else printf("Found: %d\n", aim_link->item); } } else if (cmd[0] == 'p') bst_show_by_tree(r); else if (cmd[0] == 'l') bst_inorder(r); else ; //ingnore illegal command line } return 0; } link NODE(int item, link left, link right) { link born = malloc(sizeof (node)); born->item = item; born->left = left; born->right = right; return born; } link bst_insert(link root, int item) { if (root == NULL) return NODE(item, NULL, NULL); else if(item < root->item) root->left = bst_insert(root->left, item); else if(item > root->item) root->right = bst_insert(root->right, item); else ; //ignored the repeating item; return root; } link bst_delete(link root, int item) { if (root == NULL) return NULL; else if (item < root->item) root->left = bst_delete(root->left, item); else if (item > root->item) root->right = bst_delete(root->right, item); else { if (root->left != NULL) root->left = bst_delete(root->left, root->item = pre(root)->item); else if (root->right != NULL) root->right = bst_delete(root->right, root->item = next(root)->item); else { free(root); root = NULL; } } return root; } link bst_search(link root, int item) { if (root == NULL) return NULL; else if (item < root->item) return bst_search(root->left, item); else if (item > root->item) return bst_search(root->right, item); else return root; } //has grantee root != NULL link pre(link root) { link p = root->left; while (p->right != NULL) p = p->right; return p; } //has grantee root != NULL link next(link root) { link p = root->right; while (p->left != NULL) p = p->left; return p; } void bst_inorder(link root) { inorder(root); printf("\n"); } void inorder(link root) { if (root == NULL) return; inorder(root->left); printf("%d ", root->item); inorder(root->right); } void bst_show_by_tree(link root) { char cmd[CMD_LEN]; sprintf(cmd, "rm -f ./tree_src.txt"); system(cmd); FILE *fd = fopen("./tree_src.txt", "a+"); fprintf(fd, "\n\t\\tree"); tree_print(root, fd); fprintf(fd, "\n\n"); fclose(fd); sprintf(cmd, "cat ./tree_src.txt | ~/tree/tree"); system(cmd); } void tree_print(link root, FILE *fd) { fprintf(fd, "("); if (root != NULL) { fprintf(fd, "%d", root->item); tree_print(root->left, fd); tree_print(root->right, fd); } fprintf(fd, ")"); }
测试示范
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
#返回上一级
相关文章推荐
- 二叉排序树删除、搜索、插入的迭代实现
- c++实现二叉排序树-插入-删除-递归遍历
- 数据结构与算法分析学习笔记--第四章(搜索二叉树,递归和非递归实现删除、插入)
- c++实现二叉树的查找,插入,删除,深度,叶子节点数,度为1的节点数(递归方法)及运行实例结果
- 二叉排序树插入删除的实现
- c++实现二叉树的查找,插入,删除,深度,叶子节点数,度为1的节点数(递归方法)及运行实例结果
- 二叉排序树的建立、插入、删除、查找、比较、4种遍历方式的C++完整实现版
- c++实现二叉树的查找,插入,删除,深度,叶子节点数,度为1的节点数(递归方法)及运行实例结果
- 二叉排序树节点的删除(C++,算法导论),前中后序遍历(递归/非递归,栈实现),按层次遍历(队列实现)
- 二叉排序树总结(插入,搜索,排序,中序遍地,递归,非递归)
- 二叉排序树(插入、删除、更新、遍历、搜索、求树高。。。)
- c++实现二叉树的查找,插入,删除,深度,叶子节点数,度为1的节点数(递归方法)及运行实例结果
- 二叉排序树总结(插入,搜索,排序,中序遍地,递归,非递归)
- 二叉排序树的建立、插入、删除、查找、4种遍历 C++完整实现
- AVL树非递归实现插入和删除例程
- c++实现二叉树的查找,插入,删除,深度,叶子节点数,度为1的节点数(递归方法)及运行实例结果
- 二叉排序树 插入,创建,中序遍历,最大,最小值,层级,打印,删除,搜索
- 二叉排序树(Binary Sort Tree)查找、插入、删除 Java实现
- 二叉搜索树(BST)递归与非递归的插入、删除、查找的实现
- 二叉排序树的构造,插入,删除,完整c代码实现