数据结构-二叉排序树

模范代码 :

#include<iostream>
using namespace std;

struct BSTree
{
	int key;
	BSTree *lchild,*rchild;
};

BSTree* SearchBST1(BSTree *t,int k)//二叉排序树的查找递归算法
{
	if(!t||k==t->key) return t;
	else 
	{
		if(k<t->key) return SearchBST1(t->lchild,k);//查找左孩子
		else
			return SearchBST1(t->rchild,k);//查找右孩子
	}
}

BSTree* SearchBST2(BSTree *t,int k)//二叉排序树的查找非递归算法
{
	BSTree *p = t;
	while(p!=NULL&&p->key!=k)
	{
		if(k<p->key) p=p->lchild;
		else p=p->rchild;
	}
	return p;
}

//插入一个关键字k与建立一棵二叉排序树算法是一样的
BSTree * InsertBST2(BSTree *t,int k)//插入关键字k,非递归
{
	//若二叉排序树 t 中没有关键字k,则插入,否则直接返回
	
	BSTree *p=t;//p的初值指向根结点
	BSTree *f;//f保存当前查找的结点
	while(p)//查找插入位置,插入位置一定是一个叶子结点
	{
		if(p->key==k)//树中已有k,无需插入
		{
			cout<<"树中存在"<<k<<",插入失败"<<endl;
			return t;
		}
		f=p;

		//若k<p->key,在左子树上查找,否则在右子树上查找
		p=(k<p->key)?p->lchild:p->rchild;
	}
	p = new BSTree;
	p->key=k;
	p->lchild=p->rchild=NULL;
	if(t==NULL)t=p;//插入结点为新的根结点
	else if(k<f->key)f->lchild = p;//插入结点为左孩子
	else f->rchild = p;//插入结点为右孩子
	return t;
}

BSTree * InsertBST1(BSTree *t,BSTree *p,BSTree *f,int k)//插入关键字k,递归
{
	//t二叉排序树的根,p待插入结点,初值为t, f表示p的父结点
	if(t==NULL)
	{
		p = new BSTree;
		p->key=k;
		p->lchild=p->rchild=NULL;
		t=p;//树为空,p为根
		//cout<<"插入"<<k<<endl;
	}
	else
	if(p!=NULL&&k==p->key)//树中已有k,无需插入
	{
		cout<<"树中存在"<<k<<",插入失败"<<endl;
		return t;
	}
	else
	if(p==NULL)//找到插入位置
	{
		p = new BSTree;
		p->key=k;
		p->lchild=p->rchild=NULL;
		if(k<f->key)f->lchild = p;//插入结点为左孩子
		else f->rchild = p;//插入结点为右孩子
		//cout<<"插入"<<k<<endl;
	}
	else 
	{
		if(k<p->key) 
		{
			//cout<<"左"<<endl;
			f=p;//f保存p的父结点
			InsertBST1(t,p->lchild,f,k);//查找左孩子
		}
		else 
		{
			//cout<<"右"<<endl;
			f=p;
			InsertBST1(t,p->rchild,f,k);//查找右孩子
		}
	}
	return t;
}

void DelBST(BSTree *t,int k)//删除关键字k
{
	BSTree *p=t;//p的初值指向根结点
	BSTree *f = NULL;
	BSTree *r,*s;//*s是被删结点的*p的直接前驱(中序遍历的前驱),*r是*s的双亲
	while(p)
	{
		if(p->key==k)break;//找到关键字为k的结点
		f=p;
		p=(k<p->key)?p->lchild:p->rchild;
	}
	if(!p)return;//二叉排序树中无关键字为k的结点
	if(p->lchild==NULL&&p->rchild==NULL)//*p是叶子
	{
		if(p==t)t=NULL;//*p既是叶子,又是根
		else if(p==f->lchild)f->lchild=NULL;
		else f->rchild=NULL;
		free(p);
	}
	else 
		if(p->lchild==NULL && p->rchild!=NULL) // *p只有右子树
		{
			if(f->lchild==p)
				f->lchild=p->rchild;//将*p的右子树链接到其父结点的左链上
			else 
				f->rchild=p->rchild;//将*p的右子树链接到其父结点的右链上
			free(p);
		}
	else if(p->rchild==NULL&&p->lchild!=NULL)//*p只有有左子树
	{
		if (f->lchild==p)              
			f->lchild=p->lchild; //将*p的左子树链接到其父结点的左链上
		else
			f->rchild=p->lchild; //将*p的左子树链接到其父结点的右链上
		free(p);
	}
	else if(p->lchild!=NULL&&p->rchild!=NULL)//*p既有左子树,又有右子树
	{
		r=p;s=p->lchild;
		while(s->rchild)//中序遍历*P的前驱*s,要么是叶子结点,要么没有右孩子
		{
			r=s;s=s->rchild;
		}
		p->key=s->key;//用*s替换*p
		if(r!=p) r->rchild=s->lchild;//将*s的左子树链接到*r的右链上
		else r->lchild = s->lchild;
		free(s);
	}
}
void Travel(BSTree *t)
{
	if(t==NULL)return;
	else 
	{
		Travel(t->lchild);
		cout<<t->key<<" ";
		Travel(t->rchild);
	}
}
void select()
{
	cout<<"欢迎进入二叉树排序操作界面!!!"<<endl;
	cout<<"1,初始化一棵二叉排序树"<<endl;
	cout<<"2,在二叉排序树上查找一个元素"<<endl;
	cout<<"3,在二叉排序树上插入一个元素"<<endl;
	cout<<"4,在二叉排序树上删除一个元素"<<endl;
	cout<<"5,中序遍历二叉排序树"<<endl;
	cout<<"0,操作结束"<<endl;
}
int main()
{
	BSTree *t=NULL;
	BSTree *p,*f;
	select();
	int n;
	int k;
	int i;
	while(1)
	{
		cout<<"请输入操作序号:"<<endl;
		cin>>n;
		switch(n)
		{
		case 0:exit(0);
		case 1:cout<<"请输入二叉排序树的结点个数"<<endl;
			cin>>n;
			cout<<"输入结点的值"<<endl;
			for(i=1;i<=n;i++)
			{
				cin>>k;
				//t=InsertBST2(t,k);
				t=InsertBST1(t,t,f,k);
			}
			cout<<"二叉排序树建立完成"<<endl;break;
		case 2:cout<<"请输入查找元素的值"<<endl;
			cin>>k;
			p = SearchBST1(t,k);
			if(p==NULL)cout<<k<<"不存在."<<endl;
			else cout<<k<<"存在."<<endl;break;
		case 3:cout<<"请输入插入元素的值"<<endl;
			cin>>k;
			InsertBST2(t,k);
			cout<<"插入操作完成"<<endl;
			break;
		case 4:cout<<"请输入删除元素的值"<<endl;
			cin>>k;
			DelBST(t,k);
			cout<<"删除元素成功"<<endl;break;
		case 5:cout<<"中序遍历二叉树为:"<<endl;
			Travel(t);cout<<endl;break;
		}
	}
	return 0;
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值