平衡二叉树

平衡二叉树

发展历史:

1、二叉查找树

二叉查找树(Binary Search Tree,BST)是一种特殊的二叉树,其中每个节点都满足以下两个条件:
1、左子树上所有节点的值都小于它的根节点的值。
2、右子树上所有节点的值都大于它的根节点的值。
这个特性使得我们可以非常高效地实现搜索、插入和删除等操作。
对于搜索操作,我们可以按照二分查找的思路,在每个节点处比较搜索值和节点值的大小,根据比较结果选择进入左子树或右子树,直到找到目标节点或者到达叶子节点(如果没有找到目标节点,则搜索失败)。
对于插入操作,我们从根节点开始,沿着二叉查找树一路向下,找到插入位置,并在该位置插入新节点。
对于删除操作,情况稍微复杂一些。首先,我们需要找到待删除节点的位置。如果该节点是叶子节点,直接删除即可;如果该节点只有一个子节点,用子节点替换该节点即可;如果该节点有两个子节点,我们可以选择用该节点左子树的最大节点或右子树的最小节点来替换该节点。为了保持二叉查找树的特性,我们需要保证被选择的节点不包含其他节点,否则会破坏二叉查找树的结构。

总体来说,二叉查找树是一种非常高效、灵活的数据结构,可以用于多种搜索、插入、删除等场景。但是,如果不平衡,会出现退化为链表的情况,导致效率急剧下降。因此,在实际应用中,我们通常会使用更加复杂的平衡二叉查找树,如红黑树、AVL树等,以保证树的高度在一个可控范围内,从而保持较高的性能。

2、平衡二叉树

平衡二叉树是一种特殊的二叉查找树,它的左右子树的高度差不超过1,以此保证了查找、插入、删除等操作的平均时间复杂度为O(log n)。

平衡二叉树的实现方式有很多,其中比较常见的是红黑树和AVL树。红黑树是一种近似平衡的二叉树,它能够保证在最坏情况下,任何操作的时间复杂度都是O(log n)。而AVL树是一种严格平衡的二叉树,它的左右子树高度差不超过1,能够保证任何操作的时间复杂度都是O(log n)。

相对于普通的二叉查找树,平衡二叉树在维护数据的同时,能够自动地调整树的结构,使得树的高度始终保持在O(log n)的级别,从而提高了查找、插入、删除等操作的效率。

平衡二叉树的左旋

左旋情形:
当某个节点的右子树的高度比左子树高度大 1 时,需要进行左旋操作。
平衡二叉树的左旋和右旋是指通过对节点的旋转,调整平衡二叉树中节点的位置,从而达到平衡的目的。
左旋操作是将当前节点的右子节点旋转为其父节点,并将当前节点的父节点旋转为当前节点的左子节点,如下图所示:

         |                           |
         A                           B
        / \                         / \
       B   C          -->          D   A
      / \                             / \
     D   E                           E   C

代码

private TreeNode leftRotate(TreeNode node) {
    // 获取节点的右子节点
    TreeNode right = node.right;
    // 将右子节点的左子节点设置为该节点的右子节点
    node.right = right.left;
    // 将该节点设置为右子节点的左子节点
    right.left = node;
    // 更新节点的高度
    node.height = Math.max(height(node.left), height(node.right)) + 1;
    right.height = Math.max(height(right.left), height(right.right)) + 1;
    // 返回新的根节点
    return right;
}

右旋情形:
当某个节点的左子树的高度比右子树高度大 1 时,需要进行右旋操作。
右旋操作是将当前节点的左子节点旋转为其父节点,并将当前节点的父节点旋转为当前节点的右子节点,如下图所示:


         |                           |
         A                           B
        / \                         / \
       B   C          <--          D   A
      / \                             / \
     D   E                           E   C

代码

private TreeNode rightRotate(TreeNode node) {
    // 获取节点的左子节点
    TreeNode left = node.left;
    // 将左子节点的右子节点设置为该节点的左子节点
    node.left = left.right;
    // 将该节点设置为左子节点的右子节点
    left.right = node;
    // 更新节点的高度
    node.height = Math.max(height(node.left), height(node.right)) + 1;
    left.height = Math.max(height(left.left), height(left.right)) + 1;
    // 返回新的根节点
    return left;
}

通过旋转操作,可以使得平衡二叉树在插入和删除节点时,能够保持平衡,从而保证树的查找性能。

你可能感兴趣的:(算法与数据结构,数据结构)