一、二叉排序树存在的问题
二叉排序树相关内容:二叉排序树【Java实现】
假定存在一个序列{ 1, 2, 3, 4, 5, 6, 7},创建一棵二叉排序树如下:
此时,该二叉排序树更类似于一根单链表,无法发挥二叉排序树的优势
且每次需要比较左子树,查询速度比单链表还慢
二、平衡二叉树
1. 概念
平衡二叉树也叫平衡二叉搜索树(Self-balancing Binary Search Tree),又被称为 AVL 树,可以保证查询效率很高
平衡二叉树的特点:
它是一棵空树或者它的左右两棵子树的高度差的绝对值不超过1,且其左右两棵子树都是一棵平衡二叉树
概念图示:
2. 左旋转
在构建一棵平衡二叉树的过程中,插入某一个节点后,出现了 右子树高度 - 左子树高度 > 1 时,则需要将该树进行左旋转,来降低右子树的高度,使其仍满足平衡二叉树
思路:
1.创建一个新节点,值等于当前节点的值
2.将新节点的左子树置为当前节点的左子树
3.将新节点的右子树置为当前节点右子节点的左子树
4.将当前节点的值置为当前节点的右子节点的值
5.将当前节点的右子树置为当前节点右子节点的右子树
6.将当前节点的左子节点置为新节点
思路图示:
2. 右旋转
在构建一棵平衡二叉树的过程中,插入某一个节点后,出现了 左子树高度 - 右子树高度 > 1 时,则需要将该树进行右旋转,来降低左子树的高度,使其仍满足平衡二叉树
思路:
1.创建一个新节点,值等于当前节点的值
2.将新节点的右子树置为当前节点的右子树
3.将新节点的左子树置为当前节点左子节点的右子树
4.将当前节点的值置为当前节点的左子节点的值
5.将当前节点的左子树置为当前节点左子节点的左子树
6.将当前节点的右子节点置为新节点
思路图示:
3. 双旋转
在某些情况下,单旋转无法将非平衡二叉树转成平衡二叉树(如下图),此时就需要进行双旋转
思路:
当进行右旋转时:
如果当前节点的左子节点的右子树的高度大于其左子节点的左子树的高度
则先对该节点的左子节点进行左旋转
再对该节点进行右旋转
当进行左旋转时:
如果当前节点的右子节点的左子树的高度大于其右子节点的右子树的高度
则先对该节点的右子节点进行右旋转
再对该节点进行左旋转
思路图示:
4. 代码实现
代码如下:
public class AVLTreeDemo {
public static void main(String[] args) {
int[] arr = {
10, 11, 7, 6, 8, 9};
AVLTree avlTree = new AVLTree();
for (int value : arr) {
avlTree.add(value);
}
avlTree.midOrder();
System.out.println("当前二叉树的高度:");
System.out.println(avlTree.getRoot().height());
System.out.println("当前二叉树左子树的高度:");
System.out.println(avlTree.getRoot().leftHeight());
System.out.println("当前二叉树右子树的高度:");
System.out.println(avlTree.getRoot().rightHeight());
}
}
class AVLTree {
static class Node {
private int value;
private Node left;
private Node right;
public Node() {
}
public Node(int value) {
this.value = value;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}