二叉搜索树BST

二叉搜索树

二叉排序树又称“二叉查找树”、“二叉搜索树”。

二叉排序树:或者是一棵空树,或者是具有下列性质的二叉树:

1. 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;

2. 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;

3. 它的左、右子树也分别为二叉排序树。

 

二叉排序树通常采用二叉链表作为存储结构。中序遍历二叉排序树可得到一个依据关键字的有序序列,一个无序序列可以通过构造一棵二叉排序树变成一个有序序列,构造树的过程即是对无序序列进行排序的过程。每次插入的新的结点都是二叉排序树上新的叶子结点,在进行插入操作时,不必移动其它结点,只需改动某个结点的指针,由空变为非空即可。搜索、插入、删除的时间复杂度等于树高,期望O(logn),最坏O(n)(数列有序,树退化成线性表,如右斜树)。


查找:

思路:①若二叉树为空,则找不到,②先与根比较,相等则找到,否则若小于根则在左子树上继续查找,否则在右子树上继续查找。

递归算法:

BstTree BstSearch ( BstTree bst, DataType x )

{

  if ( bst==NULL )

    return NULL;

  else if ( bst->data==x )

    return bt;

  else if ( x<bst->data )

    return BstSearch ( bst->lchild, x);

  else

    return BstSearch ( bst->rchild, x);

}

非递归算法:

BstTree BstSearch ( BstTree bst, DataType x)

{

  p =bst;

  while ( p ) {

    if ( p->data==x )

     return p;

    else if ( x<p->data )

     p = p->lchild;

    else

     p = p->rchild;

  }

  return NULL;  // not found

}


插入:

思路:先查找,若找不到则插入结点作为最后访问的叶子结点的孩子。

新插入的结点总是叶子。


建立:

经过一系列插入操作可以建立二叉排序树。

给定关键字序列,建立二叉排序树。方法:①开始二叉树为空,②对每一个关键字,先进行查找,如果已存在,则不作任何处理,否则插入。

一句话,“从空树开始,每次插入一个关键字”。


删除:要注意删除结点为根节点的情况

分三种情况:
1、叶子
直接删除即可。
2、左子树或右子树为空
将左子树或右子树接到双亲上。
3、左右子树都不为空
用左子树上最大的结点替换被删除的结点,然后删除左子树的最大结点。

#include <iostream>
using namespace std;

struct node
{
	int data;
	node *lchild,*rchild;
};

//插入
void Insert(node *&T,int data)
{
	if(T==NULL)//空树时
	{
		T=new node;
		T->data=data;
		T->lchild=NULL;
		T->rchild=NULL;
	}
	else
	{
		node *p=T,*f=NULL;
		while(p!=NULL)//查找要插入的位置
		{
			if(p->data==data)
				return;
			f=p;//记录父结点,用来最后指向新的叶子结点
			if(data<p->data)
				p=p->lchild;
			else
				p=p->rchild;
		}
		p=new node ;//产生一个叶子结点
		p->data=data;
		p->lchild=NULL;
		p->rchild=NULL;

		if(data<f->data)//将新的叶子结点加入到原树中
			f->lchild=p;
		else
			f->rchild=p;
	}
}

//建立BST
node*  Create()//生成二叉排序树
{
	node *T=NULL;
	int i;
	cin>>i;
	while(i!=-1)
	{
		Insert(T,i);
		cin>>i;
	}
	return T;
}

//中序遍历
void Print(node *T)//中序遍历
{
	if(T!=NULL)
	{
		Print(T->lchild);
		cout<<T->data<<' ';
		Print(T->rchild);
	}
}
//查找
void Find(node *T,int data,node *&f,node *&p)//返回多个值,将返回参数按引用或指针方式使用,不能传值
{
	if(T==NULL)
		return ;
	else
	{
		p=T;
		
		while(p)
		{
			
			if(p->data==data)
			{	
				//cout<<"find data= "<<p->data<<endl;
				return ;
				
			}
			f=p;//如果查找的是根节点,则f为初始值NULL,否则为p的父结点
			if(data<p->data)
			{
				p=p->lchild;
			}
			else
				p=p->rchild;
		}
		
	}
}
//删除结点
void Delete(node * &T,int data)
{
	node * f=NULL,*p=NULL;
	if(T==NULL)//空树
		return;
	Find(T,data,f,p);

	if(p==NULL)//没有找到
		return;
	if(p->lchild==NULL && p->rchild==NULL)//删除叶子结点
	{
		if(f)//非根结点
		{
			if(f->lchild==p)
			{
				f->lchild=NULL;
			}
			else
			{
				f->rchild=NULL;
			}
		}
		else
			T=NULL;
		delete p;
	}
	else if(p->lchild==NULL)
	{
		if(f)//非根结点
		{
			if(f->lchild==p)
			{
				f->lchild=p->rchild;
			}
			else
			{
				f->rchild=p->rchild;
			}
		}
		else
			T=p->rchild;
		delete p;
	}
	else//删除的结点含有左右子树:从待删除结点的左子树中选择最大值,交换,删除左子树中的最大值结点
	{
		node *p1=NULL,*p2=NULL;
		p1=p->lchild;//指向待删除结点的左子树
		p2=p1;
		while(p1!=NULL && p1->rchild!=NULL)//找最大值,p1所指向的为最大值
		{
			p2=p1;
			p1=p1->rchild;
		}
		
		p->data=p1->data;//交换
		p2->rchild=NULL;//删除
		delete p1;
		
	}
	

	
}
void main()
{
	node *T=Create();
	Print(T);
	cout<<endl;
	Insert(T,99);
	Print(T);
	cout<<endl;
	node *f=NULL,*p=NULL;
	Find(T,99,f,p);
	if(p!=NULL)
		cout<<p->data<<endl;
	int i;
	cout<<"输入要删除的数"<<endl;
	cin>>i;
	Delete(T,i);
	cout<<endl;
	Print(T);
	system("pause");
}






#include <iostream>
using namespace std;

struct node 
{
	int data;
	node *left;
	node *right;
};
void Inseart(node *&T,int data)
{
	if(T==NULL)
	{
		T=new node;
		T->data=data;
		T->left=NULL;
		T->right=NULL;
	}
	else
	{
		node *f=NULL,*p=T;
		while(p)
		{
			f=p;
			if(data==p->data)
				return;
			else if(data<p->data)
				p=p->left;
			else
				p=p->right;
		}
		p=new node ;
		p->data=data;
		p->left=NULL;
		p->right=NULL;
		if(data<f->data)
			f->left=p;
		else
			f->right=p;
	}
}
void Create(node *&T)
{
	int data;
	cin>>data;
	while(data!=-1)
	{
		Inseart(T,data);
		cin>>data;
	}
}
void Print(node *T)
{
	if(T)
	{
		Print(T->left);
		cout<<T->data<<endl;
		Print(T->right);
	}
}

void Search(node *T,int data ,node * &f,node * &p)
{
	if(T==NULL)
		return;
	p=T;
	while(p)
	{
		
		if(data==p->data)
		{
			return;
		}
		f=p;
		 if(data<p->data)
		{
			p=p->left;
		}
		else
			p=p->right;
	}
	if(p==NULL)
	{
		cout<<"not find"<<endl;
		p=f=NULL;
	}
	
}

void Delete(node * &T,int data)
{
	node *f=NULL,*p=T;
	Search(T,data,f,p);
	if(p==NULL)
		return;
	if(p->left==NULL && p->right==NULL)
	{
		if(f==p)
		{
			T=NULL;
			delete p;
		}
		else
		{
			if(f->left==p)
				f->left=NULL;
			else
				f->right=NULL;
			delete p;
		}
	}
	else if(p->left==NULL)//有右子树
	{
		if(f==p)//要删除的是根结点
		{
			T=p->right;
			delete p;
		}
		else
		{
			if(f->left==p)
				f->left=p->right;
			else
				f->right=p->right;
		}
	}
	else if(p->right==NULL)//有左子树
	{
		if(f==p)
		{
			T=p->left;
			delete p;
		}
		else
		{
			if(f->left==p)
				f->left=p->left;
			else
				f->right=p->left;
		}
	}
	else//有左右子树
	{
		node *pmax=p->left,*pre=p;
		while(pmax!=NULL && pmax->right!=NULL)
		{
			pre=pmax;
			pmax=pmax->right;
		}
		swap(pmax->data,p->data);
		delete pmax;
		if(p==pre)//左子树里没有右子树
			pre->left=NULL;
		else
			pre->right=NULL;
	}
}
void main()
{
	node* T=NULL;
	Create(T);
	Print(T);
	int data;
	cin>>data;
	Delete(T,data);
	cout<<"-------------------"<<endl;
	Print(T);
	system("pause");
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值