程序员面试宝典_第13章_数据结构基础_排序算法小结(4)

十、二叉树排序算法

[算法思想]:二叉排序树(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;
}


 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值