#include <iostream>
#include <cassert>
using namespace std;

typedef int ElemType;
struct BiTree
{
ElemType key;
BiTree* lchild;
BiTree* rchild;
};

bool SearchBiSortTree( BiTree* &T, const ElemType &key, BiTree* &F, BiTree* &P )
{
//查找成功,F指向该数据元素
//查找不成功,F指向最后访问的结点
BiTree* p = T;
F = NULL;
while ( p )
{
if ( key == p->key )
{
P = p;
return true;
}
F = p;
p = ( key < p->key )? p->lchild: p->rchild;
}
P = NULL;
return false;
}

void InsertBiSortTree( BiTree* &T, ElemType key )
{
BiTree* f = NULL;
BiTree* p = NULL;
if ( !SearchBiSortTree( T, key, f, p ) )
{
BiTree* Node = new BiTree;
Node->key = key;
Node->lchild = NULL;
Node->rchild = NULL;

if ( !T )
{
T = Node;
}
else if ( key < f->key )
{
f->lchild = Node;
}
else
{
f->rchild = Node;
}
}
}



void DeleteBiSortTree( BiTree* &T, ElemType key )
{
BiTree* f = NULL;
BiTree* p = NULL;
BiTree* q = NULL;
if ( SearchBiSortTree( T, key, f, p ) )
{
assert( p != NULL );
if ( p->lchild == NULL && p->rchild == NULL )//叶子结点
{
if( f == NULL )
{
T = NULL;
}
else
{
f->lchild = NULL;
f->rchild = NULL;
}
delete p;
p = NULL;

}
else if ( p->rchild && !p->lchild )//只有右子树
{
/*q = p; //因为本程序中,
//SearchBiSortTree( BiTree* &T, const ElemType &key, BiTree* &F, BiTree* &P )
//P不是二叉树的引用,而是指针BiTree* p = NULL;的引用,故不能这么写
p = p->rchild;
delete q;
q = NULL;*/
if ( f == NULL )
{
T = p->rchild;
}
else
{
if ( p->key < f->key ) //小于删除节点父节点的值,插入父节点左子树中
{
f->lchild = p->rchild;
}
else //大于删除节点父节点的值,插入父节点右子树中
{
f->rchild = p->rchild;
}
}

delete p;
p = NULL;
}
else if ( p->lchild && !p->rchild ) //只有左子树
{
/*q = p; //因为本程序中,
//SearchBiSortTree( BiTree* &T, const ElemType &key, BiTree* &F, BiTree* &P )
//P不是二叉树的引用,而是指针BiTree* p = NULL;的引用,故不能这么写

p = p->lchild;
delete q;
q = NULL;*/

if ( f == NULL )
{
T = p->lchild;
}
else
{
if ( p->key < f->key ) //小于删除节点父节点的值,插入父节点左子树中
{
f->lchild = p->lchild;
}
else //大于删除节点父节点的值,插入父节点右子树中
{
f->rchild = p->lchild;
}
}
delete p;
p = NULL;
}
else //左右子树都有,删除*p
{
//方法一:令*p的左子树为*f的左子树,而*p的右子树为*s的右子树,*s指向*p左子树上的最右下的节点

/*if ( p->key < f->key ) //小于删除节点父节点的值,插入父节点左子树中
{
BiTree* s = p;
//首先找到*p左子树上的最右下的节点
while( s->rchild )
{
s = s->rchild;
}
f->lchild = p->lchild;
s->rchild = p->rchild;
delete p;
p = NULL;
}
else //大于删除节点父节点的值,插入父节点右子树中
{
BiTree* s = p;
//首先找到*p左子树上的最右下的节点
while( s->rchild )
{
s = s->rchild;
}
f->rchild = p->lchild;
s->rchild = p->rchild;
delete p;
p = NULL;
}*/

//方法二:令*p的直接前驱(或直接后继)替代*p,然后再从二叉树中删除*p的直接前驱(或直接后继)
//以下用直接前驱实现,直接后继类似(未用父指针,简单一些)

BiTree* s = p->lchild;
BiTree* sf = p; //sf为s的父节点
//首先找到*p的直接前驱
while( s->rchild )
{
sf = s;
s = s->rchild;
}
p->key = s->key;
if ( sf = p )
{
sf->lchild = s->lchild;
}
else
{
sf->rchild = s->lchild;
}
delete s;
s = NULL;
}
}
}

//释放空间
void DestroyBiSortTree ( BiTree* &T )
{
if ( T )
{
if ( !T->lchild && !T->rchild )
{
delete T;
T = NULL;
return;
}
DestroyBiSortTree( T->lchild );
DestroyBiSortTree( T->rchild );
}
}


//中序遍历二叉排序树
void InOrederTraverse( const BiTree* T )
{
if ( T )
{
InOrederTraverse( T->lchild );
cout << T->key << " ";
InOrederTraverse( T->rchild );
}
}


int main()
{
BiTree* T = NULL;
ElemType e;
while ( cin >> e )
{
InsertBiSortTree( T, e );
}

cout << "中序遍历二叉排序树:";
InOrederTraverse( T );
cout << endl;

cin.clear();
cout << "请输入你要查找的元素:";
while ( cin >> e )
{
BiTree* f = NULL;
BiTree* p = NULL;
if ( SearchBiSortTree( T, e, f, p ) )
{
cout << "查找成功" << p->key << endl;
}
cout << "请继续输入你要查找的元素:";
}

cin.clear();
cout << "请输入你要删除的元素:";
while ( cin >> e )
{
DeleteBiSortTree( T, e );

cout << "删除元素后中序遍历二叉排序树:";
InOrederTraverse( T );
cout << endl;

cout << "请继续输入你要删除的元素:";
}

DestroyBiSortTree( T );


return 0;
}