• 二叉搜索树


    二叉搜索树算法:
    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);
    	}
    }
    

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

  • 相关阅读:
    Flutter中的剪裁
    flutter设置沉浸式状态栏
    flutter设置主题色和状态栏颜色
    Flutter更改状态栏颜色
    前端基础之JavaScript
    前端基础之CSS
    前端基础之初识 HTML
    socket及其相关(续篇)
    初识socket
    面向对象及其相关
  • 原文地址:https://www.cnblogs.com/fistao/p/3051774.html
Copyright © 2020-2023  润新知