二叉搜索树的节点删除
2018-01-31 21:57
183 查看
这个程序写地可真累呀,我完完全全照着算法写的,怎么每次输出的序列都不对呢,只好亲自设置了一些序列加以调试,后来发现唯一的错误:在某个很不起眼的地方把==写成了=,我的天哪!想想因为这个小问题影响了我一天的心情真的是不值。。
算法描述:
二叉搜索树节点的删除最麻烦的地方在于,删除一个节点后,还要保持原有的性质。这就意味着要用被删点的后继点来补位,对不同的情况,后继点的位置不同,寻找方法也有所区别,还要理顺补位后的关系。
参考内容:
《算法导论》,网易公开课:算法导论。
读这个代码需要注意的地方
输入:一串字符数组 一个小于字符串数组长度的正整数m,例如:
6453872 3
程序的运行过程:把字符串数组转化为一棵二叉搜索树,然后中序遍历输出(对于二叉树中序为顺序),然后删除二叉搜索树中的第m个节点(即字符串数组中第m个数字),再次中序遍历输出,
最后,为了表示二叉搜索树不丢失输入信息,把最初输入的字符串原样输出。
输出:
对应于输入样例的输出应为:
2 3 4 5 6 7 8
2 3 4 6 7 8
6453872
多画图以帮助理解。
算法描述:
二叉搜索树节点的删除最麻烦的地方在于,删除一个节点后,还要保持原有的性质。这就意味着要用被删点的后继点来补位,对不同的情况,后继点的位置不同,寻找方法也有所区别,还要理顺补位后的关系。
参考内容:
《算法导论》,网易公开课:算法导论。
读这个代码需要注意的地方
输入:一串字符数组 一个小于字符串数组长度的正整数m,例如:
6453872 3
程序的运行过程:把字符串数组转化为一棵二叉搜索树,然后中序遍历输出(对于二叉树中序为顺序),然后删除二叉搜索树中的第m个节点(即字符串数组中第m个数字),再次中序遍历输出,
最后,为了表示二叉搜索树不丢失输入信息,把最初输入的字符串原样输出。
输出:
对应于输入样例的输出应为:
2 3 4 5 6 7 8
2 3 4 6 7 8
6453872
多画图以帮助理解。
代码
#include<cstdio> #include<cstring> #include<cstdlib> #include<queue> using namespace std; #define NIL 0x3f //最简单地构造二叉搜索树 void TREE_INSERT(int*KEY,int*LEFT,int*RIGHT,int*PARENT,int N) { for(int i=2;i<=N;i++) { int y=NIL,x=1; while(x!=NIL ) { y=x; if(KEY[i]<KEY[x]) x=LEFT[x]; else x=RIGHT[x]; } PARENT[i]=y; if (KEY[i]<KEY[y]) LEFT[y]=i;//树的根为KEY[1]是既定事实,所以i直接从2开始与KEY[1]开始比较,也不可能存在y==NIL的情况,NIL设置大了后在这里爆栈 else RIGHT[y]=i; } } void OUT_PUT(int*KEY,int*LEFT,int*RIGHT,int k) { if(LEFT[k]!=NIL) OUT_PUT(KEY,LEFT,RIGHT,LEFT[k]); printf("%d ",KEY[k]); if(RIGHT[k]!=NIL) OUT_PUT(KEY,LEFT,RIGHT,RIGHT[k]); } int TREE_MINIMUM(int*KEY,int*LEFT,int k)//返回第k个节点子树中的最小值 { while(LEFT[k]!=NIL) k=LEFT[k]; return k; } int TREE_MAXMUM(int*KEY,int*RIGHT,int k)//返回第k个节点子树中的最大值 { while(RIGHT[k]!=NIL) k=RIGHT[k]; return k; } int TREE_SUCCESSOR(int*KEY,int*PARENT,int *LEFT,int*RIGHT,int k)//返回第k个数字的后继,如果k为最大值,则最终返回NIL, { if(RIGHT[k]!=NIL) return TREE_MINIMUM(KEY,LEFT,RIGHT[k]);//本程序并没有用到这个函数,但是用到了其中的算法,把它单独写出来帮助读者理解DELETE函数的代码 int y=PARENT[k]; while(y!=NIL && k==RIGHT[y]) { k=y; y=PARENT[y]; } return y; } int Troot=1; void TRANSPLANT(int*KEY,int*LEFT,int*RIGHT,int*PARENT,int u,int v)//用v子树替换u子树 { int p=PARENT[u]; if(p==NIL) Troot=v; else if(u==LEFT[p]) LEFT[p]=v; else RIGHT[p]=v; if(v!=NIL) PARENT[v]=p; } void TREE_DELETE(int*KEY,int*LEFT,int*RIGHT,int*PARENT,int k) { if(LEFT[k]==NIL) TRANSPLANT(KEY,LEFT,RIGHT,PARENT,k,RIGHT[k]); else if(RIGHT[k]==NIL) TRANSPLANT(KEY,LEFT,RIGHT,PARENT,k,LEFT[k]); else { int y=TREE_MINIMUM(KEY,LEFT,RIGHT[k]); if(PARENT[y]!=k) { TRANSPLANT(KEY,LEFT,RIGHT,PARENT,y,RIGHT[y]); RIGHT[y]=RIGHT[k]; PARENT[RIGHT[y]]=y; } TRANSPLANT(KEY,LEFT,RIGHT,PARENT,k,y); LEFT[y]=LEFT[k]; PARENT[LEFT[y]]=y; } } int main() { char import[1010];//把输入的字符串变成数组Array,从Array[1]开始放数字 int key,N=0,M=0; scanf("%s%d",import,&M); N=strlen(import); int*KEY=(int*)malloc(sizeof(int)*(N+2)); for(int i=1;i<=N;i++) KEY[i]=import[i-1]-48; int *LEFT=(int*)malloc(sizeof(int)*(N+2));fill(LEFT,LEFT+(N+2),NIL);//见鬼呀哈哈,原来memset不是填值呀,填值应当用fill int *RIGHT=(int*)malloc(sizeof(int)*(N+2));fill(RIGHT,RIGHT+(N+2),NIL); int *PARENT=(int*)malloc(sizeof(int)*(N+2));fill(PARENT,PARENT+(N+2),NIL); TREE_INSERT(KEY,LEFT,RIGHT,PARENT,N); OUT_PUT(KEY,LEFT,RIGHT,Troot); printf("\n"); TREE_DELETE(KEY,LEFT,RIGHT,PARENT,M); OUT_PUT(KEY,LEFT,RIGHT,Troot); printf("\n"); for(int i=1;i<=N;i++) printf("%d",KEY[i]); return 0; }
相关文章推荐
- 专题:二叉搜索树节点的删除
- 二叉搜索树建立、插入、删除、前继节点、后继节点之c++实现
- LeetCode-450 二叉搜索树删除一个节点
- Java实现二叉搜索树节点的删除
- [LeetCode] Delete Node in a BST 删除二叉搜索树中的节点
- 【LeetCode450】Delete Node in BST二叉搜索树删除节点
- 算法导论第十二章-二叉搜索树的插入(递归与非递归),中序输出(递归,用栈,既不用栈也不递归)以及节点的删除
- 二叉搜索树的相关操作:插入节点,删除节点,排序,查找,最大值,最小值,前序,中序,后序遍历(主要用到递归的方法)
- 二叉搜索树删除节点完美版
- 数据结构与算法分析(Java语言描述)(18)—— 二叉搜索树最大、最小子节点的搜索、删除
- 二叉搜索树非递归方式删除节点
- 二叉搜索树——删除节点
- 二叉搜索树非递归方式删除节点
- 二叉搜索树节点删除 java实现
- 二叉搜索树删除节点
- 数据结构与算法分析(Java语言描述)(19)—— 二叉搜索树删除指定的节点
- Program work 7. 用数组实现一棵二叉搜索树的建立与节点删除操作
- (二叉搜索树10.1.2)POJ 1577 Falling Leaves(根据删除叶子节点的顺序输出计算一颗二叉树的前序遍历序列)
- JqueryDOM操作-删除节点
- JavaScript删除所有子节点的方法