详解Java数据结构之平衡二叉树

详解Java数据结构之平衡二叉树

什么是平衡二叉树?

平衡二叉树(Balanced Binary Tree)是一种特殊的二叉搜索树,它的左子树和右子树的高度差不超过1,这样可以保证在最坏情况下,查找、插入、删除等操作的时间复杂度都是O(log n)。

平衡二叉树的基本性质

  1. 左子树和右子树的高度差不超过1。

  2. 平衡二叉树的左右子树也是平衡二叉树。

如何实现?

平衡二叉树的实现有多种,其中比较常见的是AVL树和红黑树。

AVL树

AVL树是一种严格平衡的二叉树,它的平衡条件是:对于AVL树上的任意结点,它的左子树和右子树的高度差不超过1。

红黑树

红黑树是一种非严格平衡的二叉树,它的平衡条件是:红黑树上的任意结点,到它的叶子节点的路径上,黑色结点数目相同。红黑树通过旋转和变色来保证平衡。

平衡二叉树的应用

平衡二叉树常用于需要高效查找、插入、删除操作的场景,比如数据库索引、缓存等。

示例如何定义一棵平衡二叉树

以下是用Java代码定义一棵基于AVL树的平衡二叉树:

public class AVLTree<T extends Comparable<T>> {
    private static class AVLNode<T> {
        T element;
        AVLNode<T> left;
        AVLNode<T> right;
        int height;
        AVLNode(T theElement, AVLNode<T> lt, AVLNode<T> rt) {
            element = theElement;
            left = lt;
            right = rt;
            height = 0;
        }
    }

    private AVLNode<T> root;

    public AVLTree() {
        root = null;
    }

    public void insert(T x) {
        root = insert(x, root);
    }

    private AVLNode<T> insert(T x, AVLNode<T> t) {
        if (t == null) {
            return new AVLNode<>(x, null, null);
        }

        int compareResult = x.compareTo(t.element);

        if (compareResult < 0) {
            t.left = insert(x, t.left);
            if (height(t.left) - height(t.right) == 2) {
                if (x.compareTo(t.left.element) < 0) {
                    t = rotateWithLeftChild(t);
                } else {
                    t = doubleWithLeftChild(t);
                }
            }
        } else if (compareResult > 0) {
            t.right = insert(x, t.right);
            if (height(t.right) - height(t.left) == 2) {
                if (x.compareTo(t.right.element) > 0) {
                    t = rotateWithRightChild(t);
                } else {
                    t = doubleWithRightChild(t);
                }
            }
        } else {
            // element is already in the tree, do nothing
        }
        t.height = Math.max(height(t.left), height(t.right)) + 1;
        return t;
    }

    private int height(AVLNode<T> t) {
        return t == null ? -1 : t.height;
    }

    private AVLNode<T> rotateWithLeftChild(AVLNode<T> k2) {
        AVLNode<T> k1 = k2.left;
        k2.left = k1.right;
        k1.right = k2;
        k2.height = Math.max(height(k2.left), height(k2.right)) + 1;
        k1.height = Math.max(height(k1.left), k2.height) + 1;
        return k1;
    }

    private AVLNode<T> rotateWithRightChild(AVLNode<T> k1) {
        AVLNode<T> k2 = k1.right;
        k1.right = k2.left;
        k2.left = k1;
        k1.height = Math.max(height(k1.left), height(k1.right)) + 1;
        k2.height = Math.max(height(k2.right), k1.height) + 1;
        return k2;
    }

    private AVLNode<T> doubleWithLeftChild(AVLNode<T> k3) {
        k3.left = rotateWithRightChild(k3.left);
        return rotateWithLeftChild(k3);
    }

    private AVLNode<T> doubleWithRightChild(AVLNode<T> k1) {
        k1.right = rotateWithLeftChild(k1.right);
        return rotateWithRightChild(k1);
    }

    public void remove(T x) {
        root = remove(x, root);
    }

    private AVLNode<T> remove(T x, AVLNode<T> t) {
        if (t == null) {
            return t;
        }

        int compareResult = x.compareTo(t.element);

        if (compareResult < 0) {
            t.left = remove(x, t.left);
            if (height(t.right) - height(t.left) == 2) {
                if (height(t.right.right) >= height(t.right.left)) {
                    t = rotateWithRightChild(t);
                } else {
                    t = doubleWithRightChild(t);
                }
            }
        } else if (compareResult > 0) {
            t.right = remove(x, t.right);
            if (height(t.left) - height(t.right) == 2) {
                if (height(t.left.left) >= height(t.left.right)) {
                    t = rotateWithLeftChild(t);
                } else {
                    t = doubleWithLeftChild(t);
                }
            }
        } else if (t.left != null && t.right != null) {
            t.element = findMin(t.right).element;
            t.right = remove(t.element, t.right);
            if (height(t.left) - height(t.right) == 2) {
                if (height(t.left.left) >= height(t.left.right)) {
                    t = rotateWithLeftChild(t);
                } else {
                    t = doubleWithLeftChild(t);
                }
            }
        } else {
            t = (t.left != null) ? t.left : t.right;
        }

        if (t != null) {
            t.height = Math.max(height(t.left), height(t.right)) + 1;
        }
        return t;
    }

    private AVLNode<T> findMin(AVLNode<T> t) {
        if (t == null) {
            return null;
        }
        if (t.left == null) {
            return t;
        }
        return findMin(t.left);
    }

    public void makeEmpty() {
        root = null;
    }

    public boolean isEmpty() {
        return root == null;
    }
}

示例说明

假设我们有以下整数序列需要插入到一棵基于AVL树的平衡二叉树中:1, 2, 3, 4, 5, 6, 7, 8。

AVLTree<Integer> avlTree = new AVLTree<>();
avlTree.insert(1);
avlTree.insert(2);
avlTree.insert(3);
avlTree.insert(4);
avlTree.insert(5);
avlTree.insert(6);
avlTree.insert(7);
avlTree.insert(8);

在插入完上述整数序列后,我们可以使用以下代码检查平衡二叉树的平衡性:

private static <T extends Comparable<T>> boolean checkBalance(AVLTree.AVLNode<T> t) {
    if (t == null) {
        return true;
    }
    int leftHeight = height(t.left);
    int rightHeight = height(t.right);
    if (Math.abs(leftHeight - rightHeight) > 1) {
        return false;
    }
    return checkBalance(t.left) && checkBalance(t.right);
}

private static <T extends Comparable<T>> int height(AVLTree.AVLNode<T> t) {
    return t == null ? -1 : t.height;
}

boolean isBalanced = checkBalance(avlTree.root);

如果isBalanced等于true,则说明平衡二叉树插入所有整数后仍然平衡。

接下来,我们尝试从平衡二叉树中删除元素8:

avlTree.remove(8);

然后,我们可以使用以下代码检查AVL树的平衡性:

boolean isBalanced = checkBalance(avlTree.root);

如果isBalanced等于true,则说明AVL树删除元素8后仍然平衡。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解Java数据结构之平衡二叉树 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • 题目 3158: 蓝桥杯2023年第十四届省赛真题-三国游戏(贪心)

    题目描述 小蓝正在玩一款游戏。游戏中魏蜀吴三个国家各自拥有一定数量的士兵X, Y, Z (一开始可以认为都为 0 )。游戏有 n 个可能会发生的事件,每个事件之间相互独立且最多只会发生一次,当第 i 个事件发生时会分别让 X, Y, Z 增加Ai , Bi ,Ci 。当游戏结束时 (所有事件的发生与否已经确定),如果 X, Y, Z 的其中一个大于另外两个之…

    算法与数据结构 2023年4月30日
    00
  • golang中set数据结构的使用示例

    Golang中Set数据结构的使用示例 Set是一种无序的、元素不重复的数据结构。通过使用map来实现,map中的key即为Set中的元素,value则可以用来存储某种状态(比如计数)。 Set数据结构的定义 type Set struct { m map[interface{}]bool } Set数据结构的初始化 func NewSet() *Set {…

    数据结构 2023年5月17日
    00
  • C++数据结构关于栈迷宫求解示例

    C++数据结构关于栈迷宫求解示例攻略 在本篇攻略中,我们将使用C++数据结构中的栈来解决迷宫问题,具体将通过两个示例来详细讲解该方法。首先介绍一下栈的概念。 栈的概念 栈是一种“后入先出”的数据结构,即最后压入栈中的元素会首先被弹出,而最早压入栈中的元素会最后被弹出。栈的基本操作有入栈(push)、出栈(pop)、判断是否为空以及读取栈顶元素等。 迷宫问题 …

    数据结构 2023年5月17日
    00
  • 【ACM算法竞赛日常训练】DAY5题解与分析【储物点的距离】【糖糖别胡说,我真的不是签到题目】| 前缀和 | 思维

    DAY5共2题: 储物点的距离(前缀和) 糖糖别胡说,我真的不是签到题目(multiset,思维) ? 作者:Eriktse? 简介:19岁,211计算机在读,现役ACM银牌选手?力争以通俗易懂的方式讲解算法!❤️欢迎关注我,一起交流C++/Python算法。(优质好文持续更新中……)?? 原文链接(阅读原文获得更好阅读体验):https://www.eri…

    算法与数据结构 2023年4月18日
    00
  • C++数据结构之二叉搜索树的实现详解

    C++数据结构之二叉搜索树的实现详解 1. 什么是二叉搜索树? 二叉搜索树是一种二叉树,其中每个节点都包含一个键值,且每个节点的键值都大于其左子树中任何节点的键值,小于其右子树中任何节点的键值。如下图所示: 9 / \ 4 15 / \ 12 20 在上面的二叉搜索树中,节点的键值分别是9, 4, 15, 12, 20,且每个节点的键值都符合上述定义。 2.…

    数据结构 2023年5月17日
    00
  • nginx内存池源码解析

    Nginx内存池源码解析 Nginx是一个高性能、高并发的Web服务器。为了提高其性能和速度,Nginx采用了特殊的内存管理机制,即内存池。 什么是内存池? 内存池是一种高效的内存分配和管理机制。它将一块内存划分成多个大小相等的块,并按需分配给系统。当内存块不再使用时,它并不被立即释放,而是留在内存池中待重复利用。 Nginx内存池结构 Nginx内存池主要…

    数据结构 2023年5月17日
    00
  • 解析网站处理数据交换时的序列化和反序列化

    当网站处理数据交换时,数据往往要以一定的格式进行序列化和反序列化,以保证数据的传输和存储的正确性。本文将详细讲解如何解析网站处理数据交换时的序列化和反序列化。 什么是序列化和反序列化? 序列化(Serialization),简单来说就是将数据从一种特定的格式转换成字符串的过程。因此经过序列化后的数据可以通过网络传输或者存储到文件中,同时也可以减少数据传输过程…

    数据结构 2023年5月17日
    00
  • 带你了解Java数据结构和算法之高级排序

    带你了解Java数据结构和算法之高级排序攻略 什么是高级排序算法? 在计算机科学中,排序算法是将一串数据按照特定顺序进行排列的一种算法。根据数据规模、数据类型、稳定性、时间复杂度以及空间复杂度等因素,排序算法分为许多种类。高级排序算法是相对于普通排序算法而言,其时间复杂度更低、排序速度更快、稳定性更高的算法。 高级排序算法的分类及特点 高级排序算法分为内排序…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部