这个程序写地可真累呀,我完完全全照着算法写的,怎么每次输出的序列都不对呢,只好亲自设置了一些序列加以调试,后来发现唯一的错误:在某个很不起眼的地方把==写成了=,我的天哪!想想因为这个小问题影响了我一天的心情真的是不值。。
- 算法描述:
二叉搜索树节点的删除最麻烦的地方在于,删除一个节点后,还要保持原有的性质。这就意味着要用被删点的后继点来补位,对不同的情况,后继点的位置不同,寻找方法也有所区别,还要理顺补位后的关系。 - 参考内容:
《算法导论》,网易公开课:算法导论。
读这个代码需要注意的地方
- 输入:一串字符数组 一个小于字符串数组长度的正整数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;
}