> 文档中心 > 问AVL为何物,我愿称之为转转转

问AVL为何物,我愿称之为转转转


AVL(自平衡二叉树)

AVL树的概念,AVL树的创建思想与算法步骤,AVL树的代码实现与分析展开阐述并图解分析

若有不足之处,欢迎指出

博主空间https://blog.csdn.net/JOElib?type=blog广度优先算法https://joelib.blog.csdn.net/article/details/124017974?spm=1001.2014.3001.5502多叉树与图https://joelib.blog.csdn.net/article/details/124042140?spm=1001.2014.3001.5502


目录

AVL树的概述🐼

为什么有AVL树🦁 

BST的缺陷😶‍🌫️ 

AVL的优点 😶‍🌫️

何为AVL🦁 

AVL的特征😶‍🌫️: 

AVL树的创建思路与算法步骤🐼 

图解😶‍🌫️: 

代码实现与分析🐼

节点类中🦁 

1.右旋的核心代码🐻 

代码分析🐨:

2.左旋的核心代码🐻 

代码分析🐨: 

3.判断树高的核心代码(最难)🐻

代码分析🐨:

4.建立左高与右高的方法🐻

代码分析🐨:

5,创建一个添加节点的方法🐻 

代码分析🐨:

AVL树类中🦁

6.对底层节点的方法调用即可🐻

代码分析🐨:

结论🐼 


AVL树的概述🐼

为什么有AVL树🦁 

BST的缺陷😶‍🌫️ 

  • 如果将一个有序列表构造成BST(二叉排序树)时,该树会变成一棵只有右子树或者只有左子树的二叉树,变相变成一个单向链表
  • 由于变成了单向链表,其检索效率大大降低,不能发挥BST的优势
  • 由于还要和左子树或者是右子树进行比较,检索效率可能比单向链表还低 

AVL的优点 😶‍🌫️

  •  不存在只有左子树或者是右子树的情况,检索效率大大增大

何为AVL🦁 

AVL的特征😶‍🌫️: 

  • AVL树规定左子树与右子树的高度差不可以超过1,并且在左子树和右子树中.以他们为根节点的子树仍然是一颗AVL树

AVL树的创建思路与算法步骤🐼 

  •  左旋思想与步骤
    • 创建一个新的节点,其权值等于原根节点的权值
    • 新节点的左子树等于原根节点的左子树
    • 新节点的右子树等于原根结点的右子树的左子树
    • 原根节点的权值等于其右子节点的权值
    • 原根结点的右子树等于其右子树的右子树
    • 原根结点的左子节点等于新节点
  • 右旋思想与步骤
    • 创建一个新的节点,其权值等于原根节点的权值
    • 新节点的右子树等于原根结点的右子树
    • 新节点的左子树等于原根结点的左子树的右子树
    • 原根结点的权值等于其左子节点的权值
    • 原根结点的左子树等于其左子树的左子树
    • 原根结点的右子节点等于新节点

图解😶‍🌫️

右旋


代码实现与分析🐼

节点类中🦁 

1.右旋的核心代码🐻 

public void rightRotation() { var newNode = new Node(value); newNode.right = right; newNode.left = left.right; value = left.value; left = left.left; right = newNode;    }

代码分析🐨:

        略,按照算法步骤即可

2.左旋的核心代码🐻 

    public void leftRotation() { var newNode = new Node(value); newNode.left = left; newNode.right = right.left; value = right.value; right = right.right; left = newNode;    }

代码分析🐨: 

        略,根据算法步骤即可 

3.判断树高的核心代码(最难)🐻

public int height() { return Math.max(left != null ? left.height() : 0,right != null ? right.height() : 0) + 1;    }

代码分析🐨:

  1. 这里主要运用的思想是递归与回溯思想,利用递归,底层创建了许多的Math.max()
  2. 又根据谁调用,返回值给谁的原则,成就了该方法
  3. 以下是图解:

4.建立左高与右高的方法🐻

    public int leftHeight() { if (left == null) {     return 0; } return left.leftHeight();    }    public int rightHeight() { if (right == null) {     return 0; } return right.rightHeight();    }

代码分析🐨:

  • 最重要的就是校验是否为空,其他直接调取即可 

5,创建一个添加节点的方法🐻 

public void add(Node node) { if (node == null) {     return; } if (node.value >= value) {     if (right != null) {  right.add(node);     }else {  right = node;     } }else {     if (left != null) {  left.add(node);     }else {  left = node;     } } if (rightHeight() - leftHeight() > 1) {     if (right != null && right.leftHeight() > right.rightHeight()) {  right.rightRotation();     }     leftRotation(); }else if (leftHeight() > rightHeight()) {     if (left != null && left.rightHeight() > left.leftHeight()) {  left.leftRotation();     }     rightRotation(); }    }

代码分析🐨:

  • 主要对左旋右旋操作进行讲解,前面的在BST处有详细讲解
  • 如果右子树高度与左子树高度差值大于一,说明要进行左旋操作
    • 当右子树不为空时,且右子树的左子树高度比右子树的右子树高度大,我们先要对右子树进行右旋,再进行左旋
  • 如果左子树高度与右子树高度差值大于一,说明要进行右旋操作
    • 当左子树不为空,且左子树的右子树高度比左子树的左子树高度大,我们先要对左子树进行左旋,再进行右旋

原因图解😶‍🌫️

 

未双旋转的结果

双旋转后的结果

AVL树类中🦁

6.对底层节点的方法调用即可🐻

public class AVLTree {    public Node root;    public int height(Node node) { if (node == null) {     return 0; } return node.height();    }    public void add(Node node) { if (root == null) {     root = node; }else {     root.add(node); }    }

代码分析🐨:

       


结论🐼 

         主要是对AVL树旋转问题的讲解,可能有点抽象,但是还是可以理解的,我来总结以下必须要掌握的几点:

        1.AVL树旋转的算法步骤

        2.高度的递归求解

        3.为什么要有双旋转

        🚇下一站:BST(二叉排序树)