zoukankan      html  css  js  c++  java
  • 查找(二)——基于二叉排序树的查找

        导论:首先,沿着二分查找的思路,我们构造一种二叉树来查找,这种二叉树的左子树结点都小于根节点,右子树节点都大于根节点,这样一来,所有结点算是都排好序了,接下来就可以查找

    基于二叉排序树的查找

    一.二叉排序树的定义

    所谓二叉排序树是一个什么样的东西,我们得弄清楚,以下是二叉排序树的定义:

      1.若它的左子树非空,则左子树上所有节点的值都小于根节点的值

      2.若它的右子树非空,则右子树上所有结点的值都大于根节点的值

      3.它的左子树和右子树也是一颗二叉排序树

      有了定义,很多东西就都会显而易见了:

      1.二叉排序树并不是一颗完全二叉树

      2.和二叉判定树的对比:二叉判定树是一种特殊的二叉排序树,二叉判定树多了一个限定条件:左右子树的节点数目相差最多不能超过1个(小雨或等于1)

          3.二叉排序树又名二叉查找树

       

      好了,到这里给出二叉排序树的定义

      

    typedef struct  _TreeNode
    {
    	struct _TreeNode *leftNode;
    	struct _TreeNode *rightNode;
    	TypeData data;
    }TreeNode,*TreeRoot;
    

      

    二.二叉排序树的插入

      和堆的建立和维护类似,我们首先想解决的一个问题就是:已经有了一颗二叉排序树,怎样做到将一个值插入正确的位置,

      给出二叉树的插入定义

      

    TreeNode* Insert_Tree(TreeRoot &root,TypeData key)
    {
    	if (!root)
    	{
    		TreeNode *node=new TreeNode;
    		node->data=key;
    		node->leftNode=nullptr;
    		node->rightNode=nullptr;
    		root=node;
    		return root;
    	}
    	else if (root->data==key)
    	{
    		return root;
    	}
    	else if (root->data<key)
    	{
    		return (Insert_Tree(root->rightNode,key));
    	}
    	else if (root->data>key)
    	{
    		return(Insert_Tree(root->leftNode,key));
    	}
    
    }
    

      

    这里是用递归实现的二叉排序树的插入,要注意以下几点:

        递归开始返回的终结点有两个:

                      1.当根节点为null时

                      2.根节点的data值和key相等,这个时候就不需要插入了

        插入完毕返回插入位置的结点

    三.二叉排序树的建立

        所谓二叉排序树的建立,也就是通过向一个空节点不断地插入结点来建立一颗二叉排序树,通过递归地插入,可得

    void Create_Tree(TreeRoot& root)
    {
    	TypeData key;
    	while (std::cin>>key)
    	{
    		Insert_Tree(root,key);
    	}
    }
    

      

    四.通过二叉排序树进行查找

        这里,有两种方式,递归和非递归的

        首先是递归的

    TreeNode *find_InTree(TreeRoot root,TypeData key)
    {
    	if (root)
    	{
    		if (root->data==key)
    		{
    			return root;
    		}
    		else if (root->data>key)
    		{
    			return find_InTree(root->leftNode,key);
    		}
    		else
    		{
    			return find_InTree(root->rightNode,key);
    		}
    	}
    	return nullptr;
    }
    

      然后是非递归的,用while循环代替递归达到递归的作用

    TreeNode *find_InTree2(TreeRoot root,TypeData key)
    {
    	TreeNode* p=root;
    	while (p)
    	{
    		if (p->data==key)
    		{
    			return p;
    			break;
    		}
    		else if (p->data>key)
    		{
    			p=p->leftNode;
    		}
    		else
    		{
    			p=p->rightNode;
    		}
    	}
    	return nullptr;
    }
    

      

    最后,简单地分析一下查找的时间复杂度吧!

        二叉排序树的插入过程:很明显,二叉排序树过程最好情况是O(log2(n)),最差情况是O(n),最差的情况时:二叉树变为一颗只有左子树或者只有右子树的二叉树,整个插入过程也退化成为顺序插入

        二叉排序树的创建过程:很明显,假设有n个数,建立二叉排序树就要while循环n次插入过程,也就是说创建过程为O(nlog2(n))~O(n²)之间

        二叉排序树的查找过程:很明显,基于二叉排序树的查找过程和二叉排序树的插入过程类似,时间复杂度也为O(log2(n))到O(n)之间

    最后,程序执行过程使这样的:

    排序二叉树的创建过程;

    排序二叉树的查找过程;

    这样看来,整个过程的时间复杂度为O(nlog2(n)到O(n²))之间,但是实际上表述的时候我们通常忽略创建过程,只考虑二叉树的查找过程,这样看来的话,整个过程的时间复杂度为O(log2(n))到O(n)之间

     

  • 相关阅读:
    【转】数学题目大集合
    hdu3534,个人认为很经典的树形dp
    GYM
    HDU
    POJ
    POJ
    POJ
    set的经典应用
    天梯赛训练1 7-9 集合相似度
    天梯赛训练1 7-8 查验身份证
  • 原文地址:https://www.cnblogs.com/YTYMblog/p/6130733.html
Copyright © 2011-2022 走看看