美文网首页
树结构入门教程-平衡二叉树双旋转

树结构入门教程-平衡二叉树双旋转

作者: 会上树的程序猿 | 来源:发表于2020-04-06 09:52 被阅读0次

我们在前面学习了平衡二叉树的左旋转和右旋转,在有些特殊的需求中,往往我们只通过左旋转或者是右旋转是无法完成对二叉排序树进行调整为一棵平衡二叉树的,就像下面这个数列一样时无法通过单一的旋转完成如:{10,11,7,6,8,9}

那么我们试一下将上述数列只通过单一旋转看是否能调整为一棵AVL树,如下图:

双旋转1.png

上图中左边是数列{10,11,7,6,8,9}对应的二叉排序树,我们发现 左子树高度大于右子树的,此时我们进行右旋转,那么上图中右边就是右旋转之后的结果,发现此时右子树高度-左子树高度是大于1的,按照我们之前的做法是需要进行左旋转的,在上述的场景中是不行的,我们先来分析下这个问题:

一开始我们就发现上述二叉排序树的左子树的高度是大于右子树高度的,于是我们立即对它进行右旋转,假如我们这样操作了:

  • 当我们在右旋转的时候:
  • 1.发现左子树的右子树高度大于左子树的左子树高度(如上图一样)
  • 1.1.我们先对当前左子树的右子树进行左旋转(如下图所示:)
左子树的右子树进行左旋转.png
  • 1.2.现在我们对上图右边的二叉排序树进行右旋转即可(如下图所示)
AVL树.png

经过我们左旋转和右旋转共同的操作,将上述二叉树排序树调整为一棵AVL树,接着我们通过代码来实现上述操作

代码实现

这里直接写核心代码

//节点的添加方法
//采用递归的方式来添加,需要满足二叉排序树的要求
public void add(Node node){
    if (node == null){
        return;
    }
    //判断当前传入节点的值和当前子树的根节点的值的关系
    if (node.value < this.value){
        //如果当前节点的左子节点为null,我们直接添加
        if (this.left == null){
            this.left = node;
        }else { //递归去添加
            this.left.add(node);
        }
    }else { //表示 node.value > this.value
        if (this.right ==null){
            this.right = node;
        }else {
            this.right.add(node);
        }
    }
    //当添加完一个节点后,如果(右子树的高度-左子树的高度) >1 ,我们需要左旋转
    if (getRightHeight() - getLeftHeight() >1){
            leftRotate();
        //如果当前节点的右子节点的左子节点高度 大于当前节点右子节点的右子节点高度
        if (right !=null && right.getLeftHeight() > right.getRightHeight()){
            //首先对当前节点的右子节点进行右旋转
            right.rightRotate();
            //接着我们对当前节点进行左旋转
            leftRotate();
        }else {
            leftRotate();
        }
        return;
    }
    //当添加完一个节点后,如果(左子树的高度-右子树的高度) >1 ,我们需要右旋转
    if (getLeftHeight() - getRightHeight() >1){
        //如果当前节点的左子节点的右子节点高度大于当前节点的左子节点的高度(假如: 根节点的左子树的右子节点的高度大于左子树的左子节点的高度)
        if (left !=null && left.getRightHeight() > left.getLeftHeight()){
            //首先对当前节点的左子节点进行左旋转
            left.leftRotate();
            //接着是对当前节点进行右旋转(根节点)
            rightRotate();
        }else {
            rightRotate();
        }
    }
}

双旋转核心的代码是#add方法的后面的两个if判断,注释很详细这里我们直接测试

   int [] arr = {10,11,7,6,8,9};
    AvlTree avlTree = new AvlTree();
    //创建二叉排序树
    for (int i = 0; i <arr.length ; i++) {
        Node node = new Node(arr[i]);
        avlTree.add(node);
    }
    //遍历
    System.out.println("中序遍历结果为:");
    avlTree.midOrder();
    //=======================================
    System.out.println("当前树的高度="+avlTree.getRoot().getHeight());
    System.out.println("左子树的高度="+avlTree.getRoot().getLeftHeight());
    System.out.println("右子树的高度="+avlTree.getRoot().getRightHeight());
    System.out.println("AVL树的根节点为="+avlTree.getRoot());
    System.out.println("AVL树的根节点的左子节点为="+avlTree.getRoot().left.left);
    System.out.println("AVL树的根节点的右子节点为="+avlTree.getRoot().right);
}

测试结果如下图所示:

双旋转测试结果图.png

那么关于AVL树的双旋转的学习就到这里了,完整代码已上传git

相关文章

  • 树结构入门教程-平衡二叉树双旋转

    我们在前面学习了平衡二叉树的左旋转和右旋转,在有些特殊的需求中,往往我们只通过左旋转或者是右旋转是无法完成对二叉排...

  • 树结构入门教程-平衡二叉树右旋转

    上节我们学习了AVL树的左旋转操作,当然有左旋转肯定会有右旋转操作,关于AVL树的其他就不多说了,本节我们就直蹦主...

  • MIT算法导论十 平衡搜索树一

    平衡搜索树(BST),所有操作的Θ(lgn)(平衡树有可能不是二叉树,这一节只讨论二叉树的情况) 有多重平衡树结构...

  • 音视频开发之旅(28) 算法序列 - 平衡二叉树

    目录 平衡二叉树 左旋转、右旋转、双旋转的原理 代码实现 资料 收获 上一篇我们学习实践了二叉查找树,其结合了链表...

  • 红黑树

    在记录红黑树结构之前,先了解一下平衡二叉树 平衡二叉树的定义 平衡二叉树:对于任意一个节点,其左子树和右子树的高度...

  • 树结构入门教程-平衡二叉树

    我们通过前两节的学习完成对二叉排序树的基本操作,其中需要注意是二叉排序树的删除节点哪三种场景,本篇我们来学习树结构...

  • (三)树结构---平衡二叉树的实现

    导语 平衡二叉树的概念之前已经介绍过,这里不做累述,可以参考树结构-基础,这里主要考虑代码实现和思路原理 平衡二叉...

  • innodb的b+树索引结构

    一、innodb索引结构为什么是树结构,不是hash结构。hash索引,时间复杂度为O(1),平衡二叉树的时间复杂...

  • 平衡二叉树与红黑树的对比

    AVL树(平衡二叉树) AVL树是带有平衡条件的二叉查找树,一般是用平衡因子差值判断是否平衡并通过旋转来实现平衡,...

  • 二叉树、2-3 树、红黑树

    二叉树、2-3 树、红黑树一、满二叉树二、完全二叉树三、二叉查找树四、平衡二叉树4.1 插入原理4.2 旋转问题4...

网友评论

      本文标题:树结构入门教程-平衡二叉树双旋转

      本文链接:https://www.haomeiwen.com/subject/aahvphtx.html