您的位置:首页 > 其它

二叉搜索树的节点删除

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

多画图以帮助理解。

代码

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: