查找——树结构查找技术

  树结构查找就是将查找表按照某种规律建成树结构。因为构建的树结构是按某种规律建立的,所以查找过程也遵循这种规律可以获得较高的查找效率。下面介绍两种二叉树:

  一、二叉排序树

  1、二叉排序树的定义

    二叉排序树(Binary Sort Tree)或者是一棵空树或者是具有下列性质的二叉树:

      1)若左子树不空,则左子树上所有结点的值均小于根结点的值;若右子树不空,则右子树上所有结点的值均大于跟结点的值。

      2)左右子树也分别是二叉排序树。

        

     对二叉排序树进行中序遍历得到一个按关键码有序的序列。

    以二叉链表作为二叉排序树的存储结构,二叉链表结点的类型定义如下:

      

  2、二叉排序树中的查找

    若将查找表组织为一棵二叉排序树,则根据二叉排序树的特点,查找过程为:

    1)若查找树为空,查找失败;

    2)若查找树非空,将给定关键码kx与查找树根结点的关键码进行比较:

      若相等,查找成功,介绍查找过程;

      若给定关键码kx小于根结点关键码,查找将在左子树上继续进行,转1);

      若给定关键码kx大于跟结点关键码,查找将在右子树上继续进行,转1)。

        

    二叉排序树的定义是递归的,在二叉排序树上的查找也可以用递归的算法实现(后续文章专门介绍递归算法),如下:

      

  3、在二叉排序树上插入一个结点

    二叉排序树是一个动态的查找表,排序树的结构是在查找的过程中逐渐生成的。当遇到树中不存在的关键码时,生成新结点并将其插入到树中。

    插入过程:设待插入结点的关键码为kx,为将其插入,先要在二叉排序树中进行查找——若查找成功按二叉排序树定义且待插入结点已存在,不用插入;查找不成功时,则插入该结点。因此新插入结点一定是作为叶子结点添加上去的。

    插入具体算法:

      

    其实在编写过程中有困惑在于:f结点改变t结点就改变了么?是的。困惑的原因在于总是纠结与C/C++表示指针类型表示左右孩子的地址,而Java没有显示的指针引用。

  4、构造一棵二叉排序树

    上面插入了一个结点过程和算法有了,那么如何构造一棵二叉排序树呢?实际上就是由一个空树开始逐个插入结点的过程。

    示例:设关键码序列为63,90,70,55,67,42,98,83,10,45,58,请构造一棵二叉排序树。

    构造过程示意图,如下:

      

    具体算法如下:

       

  5、在二叉排序树中删除一个结点

    删除过程:首先进行查找,失败无法删除;成功则需保证删除该结点后能保持二叉排序树的特性。设待删除结点为p(p为执行待删除结点的指针),其双亲结点为f,可分一下三种种情况具体操作:

    1)若p结点为叶结点,由于删除后不影响整棵树的特性,所以只需将被删结点的双亲结点的相应位置值改为空;

      

    2)若p是单支结点,即p结点只有左子树或者右子树,此时只需用左或右子树替换p的位置即可;

      

    3)p结点左右子树同时存在,可按中序遍历保持有序进行调整。

      

       

      

  二、平衡二叉树

  1、平衡二叉树的定义

    由上知二叉排序树的查找效率取决于二叉树的形态,二二叉排序树的形态与生成树时结点的插入次序有关。结点的插入次序往往不能预先确定,这就需要在生成树时进行动态的调整,以构造形态匀称的二叉树。平衡二叉树就是这样一种匀称的二叉排序树,什么是平衡呢?为此先介绍一个平衡因子的概念:结点的平衡因子是指该结点的左子树高度与右子树高度之差。

    平衡二叉树(Balanced Binary Tree),又称AVL树。它或是一棵空树,或是具有下列性质的二叉排序树:根结点的平衡因子绝对值不超过1;其左子树和右子树都是平衡二叉树。

      

     上图a)和b)分别是不平衡与平衡二叉排序树:每个结点旁边所注数字是该结点的平衡因子。由平衡二叉树的定义,所有结点的平衡因子只能取-1,0,1三个值之一。若二叉排序树中存在这样的结点其平衡因子的绝对值大于1,这棵树就不是平衡二叉树。

     平衡二叉树的定义如下图:

      

  2、平衡二叉树的插入及平衡调整

    在平衡二叉树上插入或删除结点后可能是二叉树失衡,因此需要对失衡的树进行平衡化调整。调整后的二叉树除了各结点的平衡因子绝对值不超过1,还必须保持二叉排序树的特性。设a结点为结点插入后失衡的最小子树根结点,对该子树进行平衡化调整归纳起来有以下4中情况:

    1)LL型——右单旋调整

    这种失衡是因为在失衡结点的左孩子的左子树上插入结点造成的。如下图示:

      

     a)所示的树为插入前的二叉树,是一棵平衡的二叉树。其中aR为结点a的右子树,bLbR分别为结点b的左右子树,三棵子树的高均为h。在a)所示二叉排序树上插入结点x,如图b)。结点b插入在结点b的左子树bL上,导致结点a的平衡因子绝对值大于1,进而以结点a为根的子树失去平衡。

    调整策略:对失衡的子树做右旋转——将结点b作为新的根结点,结点a作为结点b的右孩子。调整后二叉树如c)图示。具体LL型调整算法如下:

      

    2)RR型——左单旋调整

      

    RR型调整算法,如下:

      

    3)LR型——先左后右双旋调整

        

         

       

    4)RL型——先右后左双旋调整    

      

       

       

  3、平衡二叉树的构造

    平衡二叉树也是一种动态的查找表——树的结果不是一次生成的而是在查找的过程中,当遇到树中不存在的关键码时,生成新结点再将其插入到树中;同一要删除结点时也要先进行查找,找到结点时将其从树中删除。无论是删除还是插入操作都要求其仍能保持平衡二叉排序树的特性。

    平衡二叉树的插入与删除操作同向二叉排序树插入与删除操作过程类似,只是操作最后要判断该树是否保持平衡——若平衡则 操作结束;否则根据具体情况进行平衡调整。

    示例:已知长度为11的表:{20,2,6,28,16,36,32, 10,2,30,8}。请按表中元素的顺序构造一棵平衡二叉排序树,并求其在等概率的情况下查找成功的平均查找长度。

    构建过程如下:

      

       

       

       

       

 

未完,待续……

 

posted on 2022-02-10 22:08  池塘里洗澡的鸭子  阅读(355)  评论(0编辑  收藏  举报