#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stack>
using namespace std;
typedef struct bnode
{
int data;
struct bnode *lchild,*rchild;
}BNode,*bitree;
/*如果返回成功,p指向查找成功的那个节点,如果失败就返回查找路径上的最后一个节点,便于我插入*/
int SearchBST(bitree T,int key,bitree f,bitree &p)/*T为根节点,key为要查找的值,f为T的双亲,f的初值为NULL*/
{
if(!T)
{
p=f;//这里必须是f而不能是NULL,因为如果查找不成功p应该指向访问的最后一个节点,这个函数可能会反复递归,所以不能保证f一定是初始值NULL
return 0;
}
else
{
if(T->data==key)
{
p=T;
return 1;
}
else if(T->data<key)
return SearchBST(T->rchild,key,T,p);
else
return SearchBST(T->lchild,key,T,p);
}
}
/*插入函数*/
int InsertBST(bitree &T,int key)//这里的T要加引用
{
bitree p,s;
if(!SearchBST(T,key,NULL,p))//查找不成功才会插入呀
{
s=new BNode[sizeof(BNode)];//注意这种new的写法
s->data=key;//初始化
s->lchild=s->rchild=NULL;//初始化
if(!p)//这里必须考虑到p为空的情况,因为一开始T就是空的,现在我就让T为s
T=s;//这里也不能写p=s,p是局部变量,函数结束就释放了,而我想改变的是T
else if(key<p->data)
p->lchild=s;
else
p->rchild=s;
return 1;
}
return 0;
}
/*
删除节点p,这里没有看到f节点是因为我们不对f的左右指针进行改变,而是巧妙的针对p进行一系列修改
这里的删除分为三种情况
(1)左右子树都空:就直接让其父节点的相应指针置空即可
(2)只有左子树或只有右子树:让其父节点的相应指针指向自己的左孩子或者右孩子
(3)左右子树均不空:这里有两种套路,第一种就是先找到p节点中序遍历的直接前驱s,然后将p的父节点f的左指针指向自己的左子树,让s节点的右指针指向自己的右子树;第二种就是让中序遍历的直接前驱或者直接后继代替p自己,然后再删除中序遍历的直接前驱或者直接后继。本文使用第一种方法。
*/
int Del(bitree &p)
{
bitree q;
if(!p->lchild&&!p->rchild)//没有子女
{
q=p;
p=NULL;
delete q;
return 1;
}
if(!p->lchild&&p->rchild)//只有右儿子
{
q=p;
p=p->rchild;
delete q;
return 1;
}
if(p->lchild&&!p->rchild)//只有左儿子
{
q=p;
p=p->lchild;
delete q;
return 1;
}
if(p->lchild!=NULL&&p->rchild!=NULL)//左右都有,这里采用的是第一种思路
{
q=p->lchild;//q此时是p左子树的根节点
while(q->rchild)//向右探寻,这个循环结束时候,q指向p中序遍历的直接前驱结点
q=q->rchild;
q->rchild=p->rchild;//直接前驱节点的右指针修改为p的右子树
q=p;//此时q回到p的位置便于我delete
p=p->lchild;//而p修改为p的左子树,本质是p的父节点的左指针不再指向p而是指向p的左子树
delete q;
return 1;
}
}
/*递归的查找并找到节点删掉*/
int DeleteBST(bitree &T,int key)//这里的T要加引用
{
if(!T)
return 0;
else
{
if(T->data==key)
return Del(T);
else if(T->data>key)
return DeleteBST(T->lchild,key);
else
return DeleteBST(T->rchild,key);
}
}
void inorder(bitree bt)//中序遍历
{
bitree p=bt;
stack<bitree> s;
while(p||!s.empty())
{
while(p)
{
s.push(p);
p=p->lchild;
}
if(!s.empty())
{
printf("%d ",s.top()->data);
p=s.top()->rchild;//这一步别忘了,弹栈之后就要探索p的右子树咯
s.pop();
}
}
printf("\n");
}
int main()
{
int n,x,i;
bitree T;
while(scanf("%d",&n)!=EOF)
{
T=NULL;
for(i=0;i<n;i++)
{
scanf("%d",&x);
InsertBST(T,x);
}
inorder(T);
printf("chose a number you'd delete:\n");
scanf("%d",&x);
DeleteBST(T,x);
inorder(T);
}
}