精华内容
下载资源
问答
  • 平衡二叉树的旋转

    2019-04-15 10:31:02
    平衡二叉树的旋转平衡二叉树的旋转分四种情况,我分为两类: 1. 左左情况和右右情况,这两种情况下,非平衡二叉树调整为平衡二叉树只需经过一次旋转即可。 a. 左左情况,以左子树的根节点进行旋转,如下图B...

     平衡二叉树的旋转。

    平衡二叉树的旋转分四种情况,我分为两类:

    1. 左左情况和右右情况,这两种情况下,非平衡二叉树调整为平衡二叉树只需经过一次旋转即可。

       a. 左左情况,以左子树的根节点进行旋转,如下图B节点,进行顺时针旋转。结果如下图。

     

    b. 右右情况,该情况下和左左情况刚好对称,旋转规则是,以右子树的根节点进行旋转,如图C节点所示,进行逆时针旋转。

     

    2. 第二类,左右情况和右左情况,这两种情况下,需要经过两次旋转才能将非平衡二叉树调整为二叉树。

       c. 左右情况。首先将左子树进行旋转,把左右情况调整为左左情况。接下来的调整按左左情况进行即可。

     

    d. 右左情况。和左右情况相似,首先将右左情况调整为右右情况,然后按右右情况进行调整即可。

     

     

     

     

     

    展开全文
  • 一、平衡二叉树的定义为避免树的高度增长过快,降低二叉树的排序性能,规定在插入和删除二叉树结点时,保证任意结点的左右子树高度差的绝对值不大于1。这样的二叉树被称为平衡二叉树(Balanced Binary Tree)。二、...

    一、平衡二叉树的定义

        为避免树的高度增长过快,降低二叉树的排序性能,规定在插入和删除二叉树结点时,保证任意结点的左右子树高度差的绝对值不大于1。这样的二叉树被称为平衡二叉树(Balanced Binary Tree)。

    二、平衡因子

        平衡因子结点的平衡因子 = 结点的左子树深度 — 结点的右子树深度。若平衡因子的取值为-1、0或1时,该节点是平衡的,否则是不平衡的。

    最低不平衡结点用A表示最低不平衡结点,则A的祖先结点可能有不平衡的,但其所有后代结点都是平衡的。

    简单理解为:一个结点的左右子树高度差不超过一,超过一就不平衡,需要进行旋转。

    二、LL平衡旋转(右单旋转)

        B→根节点,B的右子树成为A的左子树

    b88ef015f0d5e76eef82d0933dd07968.png

    实现代码:

    void rRotate(Node *Parent)//LL    {        Node *subL = Parent->_pLeft;        Node *subLR = subL->_pRight;        Parent->_pLeft = subLR;        if (subLR)//左单支            subLR->_parent = Parent;        subL->_pRight = Parent;        Node *pParent = Parent->_parent;        Parent->_parent = subL;        subL->_parent = pParent;        if (NULL == pParent)//Parent是根节点            _pRoot = subL;        else if (Parent == pParent->_pLeft)            pParent->_pLeft = subL;        else            pParent->_pRight = subL;        //修改平衡因子        subL->_bf = 0;        Parent->_bf = 0;    }

        三、RR旋转(左单旋转)B左上为根,B的左子树成为A的右子树

    ce88227e18892fe1eff73afc7a8d19cc.png

    实现代码:

    void lRotate(Node *Parent)//RR    {        Node *subR = Parent->_pRight;        Node *subRL = subR->_pLeft;        Parent->_pRight = subRL;        if (subRL)        subRL->_parent = Parent;        subR->_pLeft = Parent;        subR->_parent = Parent->_parent;        Parent->_parent = subR;        Node *pParent = subR->_parent;        if (NULL == pParent)            _pRoot = subR;        else if (Parent == pParent->_pLeft)            pParent->_pLeft = subR;        else            pParent->_pRight = subR;        Parent->_bf = 0;        subR->_bf = 0;    }

    四、LR平衡双旋转(先左后右双旋转)由基础旋转组合而来

    ea739646642c02ac405130497c8fc35a.png

    实现代码:

    void lrRotate(Node *Parent)//LR    {        Node *subL = Parent->_pLeft;        Node *subLR = subL->_pRight;        int bf = subLR->_bf;        lRotate(Parent->_pLeft);        rRotate(Parent);        if (1 == bf)            subL->_bf = -1;        else if (-1 == bf)            Parent->_bf = 1;           subLR->_bf = 0;    }

    五、RL平衡旋转(先右后左双旋转)组合旋转,可以分为两步进行旋转

    be3acc1e2a157ba3aa090b48b62c2bb5.png

    实现代码:

    void rlRotate(Node *Parent)    {        Node *subR = Parent->_pRight;        Node *subRL = subR->_pLeft;        int bf = subRL->_bf;        rRotate(Parent->_pRight);        lRotate(Parent);        if (1 == bf)            Parent->_bf = -1;        else if (-1 == bf)            subR->_bf = 1;        subRL->_bf = 0;    }

    AVL树插入代码:

    bool Insert(const K& key, const V& value)    {        Node *pNew = new Node(key,value);        Node *pCur = _pRoot;        Node *parent = NULL;        if (NULL == _pRoot)        {            _pRoot = pNew;            return true;        }        while (pCur)//寻找插入位置        {            if (key < pCur->_key)            {                parent = pCur;                pCur = pCur->_pLeft;            }            else if (key > pCur->_key)            {                parent = pCur;                pCur = pCur->_pRight;            }            else                return false;        }        if (key < parent->_key)//插入元素            parent->_pLeft = pNew;        else            parent->_pRight = pNew;        pNew->_parent = parent;        //修改平衡因子        while (parent)        {            if (pNew == parent->_pLeft)                parent->_bf--;            else                parent->_bf++;            if (0 == parent->_bf)                return true;            else if (1 == parent->_bf || -1 == parent->_bf)            {                pNew = parent;                parent = parent->_parent;            }            else//2需要进行旋转            {                if (-2 == parent->_bf && -1 == pNew->_bf)//LL                    rRotate(parent);                else if (2 == parent->_bf && 1 == pNew->_bf)//RR                    lRotate(parent);                else if (-2 == parent->_bf && 1 == pNew->_bf)//LR                    lrRotate(parent);                else if (2 == parent->_bf && -1 == pNew->_bf)//RL                    rlRotate(parent);                return true;            }        }        return true;    }

    本文参考算法网平衡二叉树旋转详解,和王道论坛。

    展开全文
  • 本文介绍了 Java 中平衡二叉树的旋转的相关内容。。。


    平衡二叉树的旋转

    • 在构建一棵平衡二叉树的过程中,当有新的节点要插入时,检查是否因插入后而破坏了树的平衡,如果是,则需要做旋转去改变树的结构;
    • 由于在构建平衡二叉树的时候,当有新节点插入时,都会判断插入后时候平衡,这说明了插入新节点前,都是平衡的,即高度差绝对值不会超过1。当新节点插入后,有可能会有导致树不平衡,这时候就需要进行调整,而可能出现的情况就有4种,分别称作 左左,左右,右左,右右

    1. 左旋(逆时针)

    • 将节点的右支往左拉,右子节点变成父节点,并把晋升之后多余的左子节点出让给降级节点的右子节点;

    左旋

    • 如下图,将"15"节点进行左旋,让"15"自身把节点出让给"17"作为"17"的左树,使得"17"节点左右子树平衡,而"15"节点没有子树,左右也平衡了;

    左旋例子


    2. 右旋(顺时针)

    • 将节点的左支往右拉,左子节点变成了父节点,并把晋升之后多余的右子节点出让给降级节点的左子节点;

    右旋


    3. 左左

    • 左左即为在原来平衡的二叉树上,在节点的 左子树的左子树下,有新节点插入,导致节点的左右子树的高度差为2;
    • 如下图,为"10"节点的左子树"7",的左子树"4",插入了节点"5"或"3"导致失衡:

    左左

    • 左左调整其实比较简单,只需要 对父父父节点进行右旋 即可;
    • 如下图,对节点"10"进行右旋:

    左左调整


    4. 左右

    • 左右即为在原来平衡的二叉树上,在节点的 左子树的右子树下,有新节点插入,导致节点的左右子树的高度差为2;
    • 如下图,为"11"节点的左子树"7",的右子树"9",插入了节点"10"或"8"导致失衡:

    左右

    • 左右这种情况,进行一次旋转是不能满足我们的条件的,正确的调整方式是,先将左右进行第一次旋转,左旋将父父节点左右调整成左左,然后再对父父父节点左左进行调整,从而使得二叉树平衡;
    • 如下图,先对上图的节点"7"进行左旋,使得二叉树变成了左左,之后再对"11"节点进行右旋,此时二叉树就调整完成(第二种左右也是如此):

    左右解决


    5. 右左

    • 右左即为在原来平衡的二叉树上,在节点的右子树的左子树下,有新节点插入,导致节点的左右子树的高度差为2;
    • 如下图,为"11"节点的右子树"15",的左子树"13",插入了节点"12"或"14"导致失衡:

    右左

    • 如下图,前面也说了,右左跟左右其实互为镜像,所以调整过程就反过来,先对节点"15"进行右旋,使得二叉树变成右右,之后再对"11"节点进行左旋,此时二叉树就调整完成:

    右左解决


    6. 右右

    • 右右即为在原来平衡的二叉树上,在节点的右子树的右子树下,有新节点插入,导致节点的左右子树的高度差为2;
    • 如下图,为"11"节点的右子树"13",的左子树"15",插入了节点"14"或"19"导致失衡:

    右右

    • 右右只需对节点进行一次左旋即可调整平衡,只需要对 父父父节点进行左旋 即可;
    • 如下图,对"11"节点进行左旋:

    右右解决

    展开全文
  • 刚开始听这个平衡二叉树的旋转,一听就蒙了,后来看了很多视频,有很多的说法。下面来介绍平衡二叉树 平衡二叉树:就是每个节点的平衡因子(Balance Factor)(以下简称BF)的绝对值小于等于1,即为0或1。 而BF就是每...

    刚开始听这个平衡二叉树的旋转,一听就蒙了,后来看了很多视频,有很多的说法。下面来介绍平衡二叉树

    平衡二叉树:就是每个节点的平衡因子(Balance Factor)(以下简称BF)的绝对值小于等于1,即为0或1。

    而BF就是每个节点左子树的高度减去右子树的高度。

    平衡二叉树的旋转共有四种情况:

    下面说一个定义,新插入的节点为破坏点,而由于破坏点的存在使二叉树失衡(|BF|>1)的节点为被破坏节点

        1.LL型:即为被破坏节点的左子树的左子树插入破坏节点。如图:

     

     

     数值为10的节点的左子树(数值为9的节点)的左子树(数值为8的节点),使其不平衡,而10为被破坏节点,8为破坏节点,那么LL即为10的L的9的L,后一个L为中心,顺时针旋转10节点(右旋),则得到:

     

         RR型:即为被破坏节点的右子树的右子树插入破坏节点。如图

     

     数值为10的节点的右子树(数值为11的节点)的右子树(数值为12的节点),使其不平衡,而10为被破坏节点,12为破坏节点,那么RR即为10的R的11的R,后一个R为中心,逆时针旋转10节点(左旋),则得到:

     

        LR型:即为被破坏节点的左子树的右子树插入破坏节点。如图:

     

     无论怎么旋转发现一次都不能完成,则需先将其转化为LL型(因为LR型第一个为L,所以转化为LL型,再按上面的步骤进行旋转),又因为LL为递减的顺序,所以6应该上去,5下来;

      1.转化为LL型:

     

     这样就构成了LL型,按上面的步骤进行二次旋转

      2.按LL型处理:

     

         RL型:即为被破坏节点的右子树的左子树插入破坏节点。如图:

     

     

    先将其转化为RR型,因为RR型,从上往下为递增,因此需要将11向上,12向下,从而构造成,RR型;

      1.转化为RR型

     

       2.正常的RR旋转:

     

     注意:考试的题,二叉树会很复杂,也就是说你要正确的LR,RR,LL,RL对于哪个节点而言,这样你就会明白旋转的中心

    旋转的操作都是对不平衡的最小子树,例如如果两个节点都不平衡,则先考虑深度大的节点,因为解决这个问题以后,可能深度小的也自然而然的解决了。

    要解决旋转之后产生分支的何去何从,这是你要看分支在原图的位置,和其他点的大小关系,这样你就知道旋转之后,它要依附于哪个点

    不管怎么操作都不能改变其中序遍历的顺序

     

    认真的思考之后,不难发现,不论用什么方法,操作以后,都是让是三个点之中大小为中间的数做根,比中间数小的数,做根的左孩子,比中间数大的数,做根的右孩子,因此有一个简单的方法:

    1.不管什么结构,从最深的叶子节点向上递归查找第一个失衡的点,标号为1.

    2.再选1下面的点为2.

    3.再选2下面的点为3.

    4.不管什么结构,大小为中间的数做根,比中间数小的数,做根的左孩子,比中间数大的数,做根的右孩子

    5.然后按照分支和每个点之间的关系,补全,这样就完成了。

     

     

    例子:在如图所示的平衡二叉树中插入关键字48后得到一颗新的平衡二叉树,在新的平衡二叉树中,关键字37所在的节点的左右子节点中保存的关键字分别是:

     

     

     插入48之后如图:

     

     从下到上计算每个节点的BF;

    BF(48)=0;    BF(37)=-1;    BF(90)=0;    BF(53)=1;    BF(13)=0;    BF(24)=-2;

    发现失衡节点为24,那么24编号为1,又因为插入了48(所以造成失衡的路径应为24->53->37->48),所以2号节点为53,3号节点为37

    将三个节点排序,则37为根节点,24为左孩子,53为右孩子,如图:

     

     再按原图的关系,补全图:53右孩子为90;49比37大比53小,所以48为53的右孩子;24的左孩子为13;如图:

     

     

    可知答案为24 53;

    展开全文
  • 平衡二叉树的旋转 (LL,LR,RL,LR是新插入结点相对于不平衡结点的位置的一种称谓) 1.LL(左旋): 如图,对LL类型的操作方法:把中间结点—3“往上提 2.RR(右旋):如图,对RR类型的操作方法:把中间结点—3“往上...
  • 平衡二叉树的旋转。。 转载: https://www.cnblogs.com/cherryljr/p/6669489.html
  • 在按照二叉查找树(二叉查找树(BST:Binary Search Tree) )方式插入元素构建一个平衡二叉树...使用图形示例与实际代码结合方式对不平衡二叉树进行旋转。定义一个树节点:平衡二叉树节点定义LL型调整由于在y_6...
  • 平衡二叉树的旋转说明

    千次阅读 2018-06-24 13:51:07
    转载自:http ://www.cppblog.com/cxiaojia/archive/2012/08/20/187776.html平衡二叉树(Balanced Binary Tree)是二叉查找树一个进化体,也是第一个...平衡二叉树要求对于每一个节点来说,它左右子树高度之...
  • 二分查找树》中提到了:平衡二叉树的目的就是使得平均查找长度最短。那么这里就引出两个问题:什么是平衡二叉树?为什么平衡二叉树的平均查找长度最短?如何将非平衡二叉树调整成平衡二叉树?1. 平衡二叉树是什么鬼...
  • 平衡二叉树的旋转及其代码实现

    千次阅读 2019-04-27 08:25:33
    平衡二叉树的构造问题以及为了维护它的平衡所要进行的LL旋转、RR旋转、LR旋转、RL旋转。 一、平衡二叉树的构造 node *insert(node *root, int x) { if (root == 0) { root = &all[total++]; root->left =...
  • 对于二叉查找树,尽管查找、插入及删除操作平均运行时间为O(logn),但是它们最差运行时间...平衡二叉树又称为AVL树,它或者是一棵空树,或者是有下列性质二叉树:它左子树和右子树都是平衡二叉树,且左右...
  • 平衡二叉树的旋转 理解清楚平衡二叉树的概念。具体如何旋转是平衡二叉树保持继续平衡的,可以参考如下的两个博客和一本书。 https://www.tutorialspoint.com/data_structures_algorithms/avl_tree_algorithm.htm ...
  • 关于平衡二叉树的最重要的一句话:在构建平衡二叉树的过程中,每当插入一个结点时,先检查是否因插入而破坏了树的平衡性,若是,则找出最小不平衡子树,在保持二叉排序树特性的前提下,调整关系。 这句话意味着:...
  • 平衡二叉搜索树,又被称为AVL树,且具有以下性质:它是一棵空树或它左右两个子树高度差绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。 在插入过程中难免出现不平衡情况,而对树进行旋转就是解决不...
  • 在按照二叉查找树(二叉查找树(BST:Binary Search Tree) )方式插入元素构建一个平衡二叉树...使用图形示例与实际代码结合方式对不平衡二叉树进行旋转。定义一个树节点:平衡二叉树节点定义LL型调整由于在y_6...
  • 算法实现 平衡二叉树的

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,488
精华内容 595
关键字:

平衡二叉树的旋转