二叉排序树(二叉搜索树)

动态查找表的一种理想数据结构。

二叉排序树的定义是:二叉排序树T是一棵树,它或者是空,或者具备一下三条性质:

(1)、如果T的根节点的左子树非空,其左子树所有结点的值均小于T的根节点的值

(2)、如果T的根节点的右子树非空,其右子树所有结点的值均大于T的根节点的值
(3)、T的根结点的左右子树均为二叉排序树

下面是代码:

文件"tree.h"

#include<iostream>
#include<stack>
#include<queue>
using namespace std;

#define MAX_NODE_NUM 20 //树结点最大值
class Bin_Sort_Tree;
//树结点
class BSTnode
{
	int tag;//后序遍历作为访问标志
	int data;
	BSTnode *lchild;
	BSTnode *rchild;
	friend class Bin_Sort_Tree;
};

//二叉排序树
class Bin_Sort_Tree
{
public:	
	int Get_data(BSTnode *p)
	{
		return p->data;
	}

	bool Search_BST(BSTnode *T,int a,BSTnode *&f,BSTnode *&p)
	{
		/*-----------------------------
		/在树中查找值为a的结点,查找到 
		/了,用p保存该结点地址,f指向 
		/p的双亲结点                   
		/-----------------------------*/
		p=T;
		while(p)
		{
			if(p->data==a)
				return true;
			else if(p->data>a)
			{
				f=p;
				p=p->lchild;
			}
			else
			{
				f=p;
				p=p->rchild;
			}
		}
		return false;
	}
	
	//将值为a的结点插入树中,若值已存在,就不插入
	void Insert_BST_1(BSTnode *&T,int a)
	{
		BSTnode *f=NULL;
		BSTnode *p=NULL;
		if(Search_BST(T,a,f,p))
			return; //树中已有值相同结点,不插入
		else
		{
			BSTnode *s=new BSTnode;
			s->data=a;
			s->lchild=s->rchild=NULL;
			if(s->data>f->data)
				f->rchild=s;
			else
				f->lchild=s;
		}
	}
	
	void Insert_BST_2(BSTnode *&T,int a) //插入算法递归实现
	{	
		if(!T)
		{
			cout<<"树为空"<<endl;
			return;
		}
		if(T->data>a)
		{
			if(!T->lchild)
			{
				T->lchild=new BSTnode;
				T->lchild->data=a;
				T->lchild->lchild=NULL;
				T->lchild->rchild=NULL;
				return;
			}
			else
				Insert_BST_2(T->lchild,a);
		}
		if(T->data<a)
		{
			if(!T->rchild)
			{
				T->rchild=new BSTnode;
				T->rchild->data=a;
				T->rchild->lchild=NULL;
				T->rchild->rchild=NULL;
				return;
			}
			else
				Insert_BST_2(T->rchild,a);
		}

	}

	void Create_BSTree(BSTnode *&T) //建树
	{
		cout<<"输入二叉排序树的元素,输入-1代表结束输入:";
		int num[MAX_NODE_NUM];
		int a,i=0;
		while(cin>>a && a!=-1)
		{
			num[i]=a;
			i++;
		}
		
		if(num[0]==-1)
		{
			cout<<"排序树为空"<<endl;
			return;
		}

		int k=i;
		T=new BSTnode;
		T->data=num[0];
		T->lchild=T->rchild=NULL;
		for(i=1;i<k;i++)
			Insert_BST_1(T,num[i]);
		cout<<"____建树完成____"<<endl;
	}

	void Delete_BST(BSTnode *&T,int a)//删除结点值为a的结点
	{
		/*---------------------------------------------------------
		/ 从树中删除一个节点后,要保证删后的树还是一棵二叉排序树, 
		/ 删除前,首先是在树中查找是否有这个结点,用p指向该结点,  
		/ 用f指向p的双亲结点,这个结点在树中的位置有下面四种情况:  
		/                                                          
		/ 1:如果p指向的结点是叶子结点,那么直接将f指针的左子树或者 
		/ 右子树置空,然后删除p结点即可。                          
		/                                                          
		/ 2:如果p指向的结点是只有左子树或右子树,那么只需要让p结点 
		/ 原来在f中的位置(左子树或右子树)用p的子树代替即可。       
		/                                                          
		/ 3:如果p所指向的结点是根节点,那么直接将根节点置空        
		/                                                          
		/ 4:如果p所指向的结点左右子树都非空,为了删除p后原序列的顺 
		/ 序不变,就需要在原序列中先找出p的直接前驱(或者直接后继)  
		/ 结点用那个结点的值来代替p结点的值,然后再删掉那个直接前  
		/ 驱(或者直接后继)结点。                                   
		/ 在中序遍历序列中找结点的直接前驱的方法是顺着结点的左孩子 
		/ 的右链域开始,一直到结点右孩子为空为止。                 
		/---------------------------------------------------------*/

		BSTnode *f=NULL;
		BSTnode *p=NULL;
		BSTnode *q=NULL;
		BSTnode *s=NULL;
		if(Search_BST(T,a,f,p))
		{
			if(p->lchild && p->rchild)
			{
				q=p;
				s=p->lchild;
				while(s->rchild)
				{
					q=s;
					s=s->rchild;
				}
				p->data=s->data;
				//s指向要删除结点的直接前驱,且s是一定没有右子树的
				if(q!=p)
					q->rchild=s->lchild;
				else
					q->lchild=s->lchild;//这种情况是,q的左子树的右子树为空时
				delete s;
				cout<<"结点删除成功"<<endl;
				return ;
			}
			else 
			{
				if(!p->lchild) //左子树为空
				{
					q=p;
					p=p->rchild;
				}
				else        //右子树为空
				{
					q=p;
					p=p->lchild;
				}
				//下面将p所指向的子树连接到f所指(被删结点的双亲)的结点上
				if(!T) //被删的结点为根节点
					T=p;
				else if(q==f->lchild)
					f->lchild=p;
				else
					f->rchild=p;
				delete q;
				cout<<"结点删除成功"<<endl;
				return;
			}
		}
		else
		{
			cout<<"要删除的结点不存在"<<endl;
			return ;
		}
	}

	//下面是二叉树的四种遍历方式,都是非递归方式实现
	
	void PreOrder_Traverse(BSTnode *T) //前序遍历
	{
		stack<BSTnode *> s;
		BSTnode *p;
		p=T;
		while(p || !s.empty())
		{
			if(p)
			{
				cout<<p->data<<"  ";
				s.push(p);
				p=p->lchild;
			}
			else
			{
				p=s.top();
				s.pop();
				p=p->rchild;
			}
		}
	}

	void InOrder_Traverse(BSTnode *T) //中序遍历
	{
		stack<BSTnode *> s;
		BSTnode *p=T;
		while(p || !s.empty())
		{
			if(p)
			{
				s.push(p);
				p=p->lchild;
			}
			else
			{
				p=s.top();
				s.pop();
				cout<<p->data<<"  ";
				p=p->rchild;
			}
		}
	}

	void PostOrder_Traverse(BSTnode *T) //后序遍历
	{
		stack<BSTnode *> s;
		BSTnode *p=T;
		while(p || !s.empty())
		{
			if(p)
			{
				p->tag=0;
				s.push(p);
				p=p->lchild;
			}
			else
			{
				p=s.top();
				if(p->tag)
				{
					cout<<p->data<<"  ";
					s.pop();
					p=NULL;
				}
				else
				{
					p->tag=1;
					p=p->rchild;
				}
			}
		}
	}

	void LevelOrder_Traverse(BSTnode *T) //层次遍历
	{
		queue<BSTnode *> q;
		BSTnode *p=T;
		q.push(p);
		while(!q.empty())
		{
			p=q.front();
			q.pop();
			cout<<p->data<<"  ";
			if(p->lchild)
				q.push(p->lchild);
			if(p->rchild)
				q.push(p->rchild);
		}
	}
};

主函数"main.cpp"

#include"tree.h"

int main()
{
	Bin_Sort_Tree tree;
	BSTnode *root=NULL;
	
	cout<<"_____建立二叉排序树____"<<endl;
	tree.Create_BSTree(root);

	cout<<"前序遍历二叉树为:";
	tree.PreOrder_Traverse(root);
	cout<<endl;

	cout<<"中序遍历二叉树为:";
	tree.InOrder_Traverse(root);
	cout<<endl;

	cout<<"后序遍历二叉树为:";
	tree.PostOrder_Traverse(root);
	cout<<endl;

	cout<<"层次遍历二叉树为:";
	tree.LevelOrder_Traverse(root);
	cout<<endl;

	int data;
	BSTnode *f=NULL;
	BSTnode *p=NULL;
	cout<<"输入你要搜索的结点的值:";
	cin>>data;
	if(tree.Search_BST(root,data,f,p))
	{
		cout<<"你所搜索的结点地址为:"<<p<<endl;
		cout<<"他的双亲结点值为:"<<tree.Get_data(f)<<endl;
	}
	else
		cout<<"树中没有你要找的结点"<<endl;

	cout<<"输入你要删除的结点的值:";
	cin>>data;
	tree.Delete_BST(root,data);
	cout<<"删除后的二叉树的中序遍历为:";
	tree.InOrder_Traverse(root);
	cout<<endl;

	cout<<"输入你要插入树中的值:";
	cin>>data;
	tree.Insert_BST_2(root,data);
	cout<<"插入后,树的中序遍历为:";
	tree.InOrder_Traverse(root);
	cout<<endl;

	return 0;
}

下面是测试结果

_____建立二叉排序树____
输入二叉排序树的元素,输入-1代表结束输入:5 7 3 2 9 4 8 8 1 10 -1
____建树完成____
前序遍历二叉树为:5  3  2  1  4  7  9  8  10
中序遍历二叉树为:1  2  3  4  5  7  8  9  10
后序遍历二叉树为:1  2  4  3  8  10  9  7  5
层次遍历二叉树为:5  3  7  2  4  9  1  8  10
输入你要搜索的结点的值:7
你所搜索的结点地址为:00380D18
他的双亲结点值为:5
输入你要删除的结点的值:10
结点删除成功
删除后的二叉树的中序遍历为:1  2  3  4  5  7  8  9
输入你要插入树中的值:6
插入后,树的中序遍历为:1  2  3  4  5  6  7  8  9
Press any key to continue

按照一开始建树时的输入,生成的树为:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值