十、二叉树排序算法
[算法思想]:二叉排序树(Binary Sort Tree)又称二叉查找树,亦称二叉搜索树。 它或者是一棵空树;或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
删除算法
相对查找和插入复杂一点,根据待删除结点的孩子情况,分三种情况:没有孩子,只有一个孩子,有两个孩子。
没有孩子的情况,其父结点指向空,删除该结点。
有一个孩子的情况,其父结点指向其孩子,删除该结点。
有两个孩子的情况,当前结点与左子树中最大的元素交换,然后删除当前结点。左子树最大的元素一定是叶子结点,交换后,当前结点即为叶子结点,删除参考没有孩子的情况。另一种方法是,当前结点与右子树中最小的元素交换,然后删除当前结点。
说明如下:
1、删除的是“叶节点20“,,删除20不会破坏树的结构。如图:
2、删除”单孩子节点90“,需要把他的孩子顶上去
3、删除“左右孩子都有的节点50”,就是找到右节点的左子树最左孩子。
比如:首先 找到50的右孩子70。
然后 找到70的最左孩子,发现没有,则返回自己。
最后 原始图和最终图如下。
终于改对了,对于我这智商编程太辛苦了~
#include <iostream>
using namespace std;
class BinaryTree;
class node;
void Show(node * t);
class node
{
public:
friend class BinaryTree;
friend void Show(node * t);
node(){key=0;leftchild=NULL;rightchild=NULL;}
node(int x){key=x;leftchild=NULL;rightchild=NULL;}
private:
int key;
node* leftchild;
node* rightchild;
};
void Show(node * t)
{
cout<<t->key<<" ";
}
class BinaryTree
{
public:
BinaryTree(){head=NULL;}
~BinaryTree(){};
void Search(int data)
{
node * p=SearchP(head,data);
if (p)
{
cout<<"Find: "<<"Address: 0x"<<hex<<p<<" , "<<"Value: "<<dec<<p->key<<endl;
}else
{
cout<<"Can't Find the key! "<<endl;
}
}
void Insert(int data){InsertP(&head,data);}
void SearchInsert(int data)
{
node * p=SearchP(head,data);
if (p)
{
cout<<"Find: "<<"Address: 0x"<<hex<<p<<" , "<<"Value: "<<dec<<p->key<<endl;
}else
{
cout<<"Can't Find the key! Insert the key "<<data<<" in the tree!"<<endl;
Insert(data);
InOrder();
cout<<endl;
}
}
void Create(int A[],int length);
void Delete(int data);
void InOrder()
{
InOrderP(Show,head);
}
private:
node * head;
node * SearchP(node * t,int data)
{
if (t==NULL)
{
return NULL;
}
if (t->key==data)
{
return t;
}
if (data<t->key)
{
SearchP(t->leftchild,data);
}
else
{
SearchP(t->rightchild,data);
}
}
void InOrderP(void (*Show)(node* n),node* t)
{
if (t==NULL)
{
return;
}
InOrderP(Show,t->leftchild);
Show(t);
InOrderP(Show,t->rightchild);
}
node * InsertP(node** t,int data)//由于可能会改变头指针,因此改用二重指针
{
if ((*t)==NULL)//不存在,所以插入
{
(*t)=new node(data);
return (*t);
}
if (data<(*t)->key)
{
(*t)->leftchild=InsertP(&((*t)->leftchild),data);
}
else if (data>(*t)->key)
{
(*t)->rightchild=InsertP(&((*t)->rightchild),data);
}
return (*t);
}
};
void BinaryTree::Create(int A[],int length)
{
for (int i=0;i<length;i++)
{
Insert(A[i]);
}
}
void BinaryTree:: Delete(int data)
{
node *p=head;
node *pp=p; //p's parent
node *temp;
while (p!=NULL)
{
if (p->key==data)
{
break;
}
else if (data<p->key)
{
pp=p;
p=p->leftchild;
}
else
{
pp=p;
p=p->rightchild;
}
}
if(!p)//没找到
{
cout<<"Data "<<data<<" doesn't exist!!! Delete Fail!!!!"<<endl;
}
else //找到了
{
if(p->leftchild==NULL&&p->rightchild==NULL)//该节点为叶子节点的情况,case1
{
if(p==head)//为根节点
{
delete head;
head=NULL;
}
else//不是根节点
{
if(pp->leftchild==p)//如果p为pp的左孩子
{
pp->leftchild=NULL;
delete p;
p=NULL;
}
else//p为pp的右孩子
{
pp->rightchild=NULL;
delete p;
p=NULL;
}
}
}
else if(p->leftchild==NULL&&p->rightchild!=NULL)//该节点只有1个右孩子情况,case2
{
if(p==head)//为根节点
{
temp=p->rightchild;
delete head;
head=temp;
}
else//不是根节点
{
if (pp->leftchild==p)//如果p为pp的左孩子
{
pp->leftchild=p->rightchild;
delete p;
p=NULL;
}
else//p为pp的右孩子
{
pp->rightchild=p->rightchild;
delete p;
p=NULL;
}
}
}
else if(p->leftchild!=NULL&&p->rightchild==NULL)//该节点只有1个左孩子情况,case3
{
if(p==head)//为根节点
{
temp=p->leftchild;
delete head;
head=temp;
}
else//不是根节点
{
if(pp->leftchild==p)//如果p为pp的左孩子
{
pp->leftchild=p->leftchild;
delete p;
p=NULL;
}
else//p为pp的右孩子
{
pp->rightchild=p->leftchild;
delete p;
p=NULL;
}
}
}
else//有两个孩子的情况
{
node *q=p->rightchild;//找到右节点左子树的最左孩子;
node *qp=p;//q的父节点
while (q->leftchild!=NULL)
{
qp=q;
q=q->leftchild;
}
p->key=q->key;
if (q->rightchild!=NULL)//
{
if (qp!=p)
{
qp->leftchild=q->rightchild;
delete q;
q=NULL;
}
else
{
qp->rightchild=q->rightchild;
delete q;
q=NULL;
}
}
else//
{
if (qp!=p)
{
qp->leftchild=NULL;
delete q;
q=NULL;
}
else
{
qp->rightchild=NULL;
delete q;
q=NULL;
}
}
}
}
}
int main()
{
int A[10]={13, 29, 27, 28, 26, 30, 38, 54 , 68 ,36};
BinaryTree BT;
BT.Create(A,10);
BT.InOrder();
int data;
cout<<endl;
while(1)
{
cout<<endl;
cout<<"请输入要查找的数据: "<<endl;
cin>>data;
BT.SearchInsert(data);
cout<<"请输入要删除的数据: "<<endl;
cin>>data;
BT.Delete(data);
BT.InOrder();
}
system("pause");
return 0;
}