二叉搜索树

二叉搜索树算法:
1、直接输入搜索序列,构造出类似于折半搜索的判定树那样的树形结构,
就能很快实现搜索,这就是二叉搜索树。
2、二叉搜索树是一种动态的搜索结构,输入元素的关键码序列不同的话
会有不同形态的二叉搜索树。
3、二叉搜索树的定义:
二叉搜索树或者是一颗空树,或者是具有下列性质的二叉树。
a)每个结点都有一个作为搜索依据的关键码,所有结点的关键码各不相同
b)左子树上的所有结点的关键码都小于根结点的关键码。
c)右子树上的所有结点的关键码都大于根结点的关键码。
d)左子树和右子树也都是二叉搜索树。
由第四条可以推断出,二叉搜索树的定义也是递归的。
二叉搜索树常用来表示字典结构。

二叉搜索树的抽象类型定义:

#include<iostream>
using namespace std;
//二叉搜索树的结点表示
struct BinSearchNode
{
	int key;	//结点的关键码
	BinSearchNode *lSearchTree;	//左子树
	BinSearchNode *rSearchTree;	//右子树
	BinSearchNode()
	{
		
		lSearchTree=NULL;
		rSearchTree=NULL;
	}
};

//二叉搜索树的类定义
class BinSearchTree
{
public:
	//构造函数和析构函数
	BinSearchTree()
	{
		bsnroot=NULL;
	}
	~BinSearchTree()
	{
	}

	//二叉搜索树的关键算法,引用形参和非引用形参
	void InsertSearchNode(BinSearchNode *&bsn, int data);	//插入结点
	void DeleteSearchNode(int key,BinSearchNode *&bsn);	//删除结点
	BinSearchNode * SearchBinaryTreeCurrent(int key,BinSearchNode *&bsn);				//搜索当前结点
	
	void MidTravel(BinSearchNode *bsn);			//中序遍历输出
	BinSearchNode *MinSearch(BinSearchNode *&bsn);//寻找中序下的第一个结点指针

	BinSearchNode *ReturnSearchRoot()			//返回二叉搜索树的根结点
	{
		return bsnroot;
	}


private:
	BinSearchNode *bsnroot;						//二叉搜索树的根结点
};

二叉搜索树插入结点递归算法:
1、如果该结点为空,则该结点为空结点,则把这个值赋值给根结点。
2、如果不为空,则和父节点的键值比较,如果小于根结点,则递归建立左子树。
3、如果大于父结点,则递归建立右子树。
4、如果等于父结点,则报错。

void BinSearchTree::InsertSearchNode(BinSearchNode *&bsn, int data)
{
	if(bsn==NULL)
	{
		//错误一:忘记了新建结点,分配存储空间
		bsn=new BinSearchNode;	//新建结点
		if(bsn==NULL)cout<<"新建新结点出错"<<endl;
		else
		{
			
			bsn->key=data;
		}
	}
	else
	{
		if(data<bsn->key)	//bsn
		{
			
			InsertSearchNode(bsn->lSearchTree,data);

		}
		else if(data>bsn->key)
		{
		
			InsertSearchNode(bsn->rSearchTree,data);
		}
		else
		{
			cout<<"非法结点"<<endl;
		}
	}
}

中序遍历输出递归算法:

void BinSearchTree::MidTravel(BinSearchNode *bsn)
{
	//if(bsn==NULL)   //这样写是错的,因为每次指针为空的时候都会打印这句话
	//{
		//cout<<"这是一颗空的二叉搜索树"<<endl;
	//}
	
	if(bsn!=NULL)
	{
		MidTravel(bsn->lSearchTree);
		cout<<bsn->key<<" ";		//找到第一个结点指针
		MidTravel(bsn->rSearchTree);

	}
}

二叉搜索树的搜索算法:
1、从根结点开始,如果根结点为空,则返回空
2、如果小于根结点的值,则递归搜索左子树
3、如果大于根结点的值,则递归搜索右子树
4、否则找到了该结点,返回真

BinSearchNode* BinSearchTree::SearchBinaryTreeCurrent(int key,BinSearchNode *&bsn)
{
	if(bsn==NULL)
		return false;
	else if(bsn->key>key)
	{
		SearchBinaryTreeCurrent(key,bsn->lSearchTree);
	}
	else if(bsn->key<key)
	{
		SearchBinaryTreeCurrent(key,bsn->rSearchTree);
	}
	else
		return bsn;
	
	
}

二叉搜索树的删除结点算法:
删除算法中需要将因删除结点而断开的二叉链表重新连接起来,同时确保二叉树
性质不会失去,还要防止重新链接后的树的高度不会增加。
规则:右子树为空,左子女填补;左子树为空,右子女填补;左子树和右子树
都不为空,则寻找中序下的第一个结点,关键码最小的结点。如果是第二小,
则右子树中有小于根结点的结点,失去了二叉搜索树的性质。
1、搜索定位到该键值对应的指针处。
2、判断该该指针的右子树为空,则将该结点赋值给一个临时指针,然后将左子树覆盖这个指针,删除临时指针。
3、如果左子树为空,则用右子女代替。
4、如果左子树和右子树都不为,则搜索该结点的右子树中搜索中序下的第一个结点,
赋值给该结点,再处理该中序结点的删除问题。:以删除的结点值的键值为键值,在当前结点的右子树中递归搜索删除该结点。
5、如果左右子树都为空,则直接删除。

void BinSearchTree::DeleteSearchNode(int key,BinSearchNode *&bsn)
{
	//错误:current这个本地指针不是引用型形参,修改它的的情况未知,诀窍,只有引用型形参才能这样用
	if(key>bsn->key)DeleteSearchNode(key,bsn->rSearchTree);
	else if(key<bsn->key)DeleteSearchNode(key,bsn->lSearchTree);
	else
	{
		BinSearchNode *p=NULL;
		if(bsn->lSearchTree!=NULL&&bsn->rSearchTree!=NULL)
		{
			//下列写法不对
			//要删除结点有两个子树
			/*p=bsn;
			//1、找到最小的键值
			//bsn=bsn->rSearchTree;  这样写难道有错?
			bsn=bsn->rSearchTree;
			while(bsn->lSearchTree!=NULL)bsn=bsn->lSearchTree;
			p->key=bsn->key;
			//2、递归删除
			DeleteSearchNode(bsn->key,bsn);*/
			p=bsn->rSearchTree;	//在右子树中寻找中序下的第一个结点
			while(p->lSearchTree!=NULL)
				p=p->lSearchTree;	//第一个左子树

			bsn->key=p->key;	//用该结点值取代根结点数据
			DeleteSearchNode(bsn->key,bsn->rSearchTree);
			//:以删除的结点值的键值为键值,在当前结点的右子树中递归搜索删除该结点。
		}
		else
		{
			//引用型指针参数自动带动相关结点的修改
			p=bsn;
			//被删除结点有一个子树
			if(bsn->lSearchTree==NULL)
				bsn=bsn->rSearchTree;
			else
				bsn=bsn->lSearchTree;
			delete p;
		}
	}
}

/*
寻找中序下的第一个结点指针:
*/
BinSearchNode* BinSearchTree::MinSearch(BinSearchNode *&bsn)
{
	if(bsn!=NULL)
	{
		MinSearch(bsn->lSearchTree);
		return bsn;
		MinSearch(bsn->rSearchTree);
	}
}

二叉搜素树是一种重要的搜索结果,下一节将构造一颗更优的二叉搜索树。

原文地址:https://www.cnblogs.com/fistao/p/3051774.html