您的位置:首页 > 其它

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

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: 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


#返回上一级
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐