平衡查找树
AVL树
平衡二叉查找树,又称 AVL树。 它除了具备二叉查找树的基本特征之外,还具有一个非常重要的特点:
它 的左子树和右子树都是平衡二叉树,且左子树和右子树的高度差不超过1。
二叉查找树的平衡只有在插入或者删除结点时才会被扰乱,因此,在这些操作过程中,AVL树需要重新排列结点以维持平衡。
平衡结点:如果结点是一棵平衡树的根,即该结点的两棵子树高度之差不超过1,则该结点就是平衡的。
以下N表示最接近新叶子的不平衡结点,经过一次单旋转和一次双旋转就可以恢复树的平衡。应保证每次插入之前树是平衡的,则插入之后不会有比N更高的不平衡点。
在插入或删除元素的过程中的一次单旋转或一次双旋转可恢复AVL树的平衡。
单旋转
右旋转
图(a)是一棵AVL子树,子树T
1、T
2、T3的高度相同。现将一个叶子结点插入T1,假设插入使得T1高度加1,则以结点N为根的子树不再平衡,此时结点N不再是平衡结点。对结点C的右旋转可恢复树的平衡。
结点N的值比结点C的值和T1的所有值都大,而且T2的所有值又比结点C的值大,因此对C的右旋转可以维持该关系。
左旋转
同理
—————————————————————————————————————————————————————————————
单旋转结论
AVL树的结点N的不平衡可以通过单旋转纠正,如果:
- 结点插在N的左孩子的左子树中,可通过右旋转达到平衡
- 结点插在N的右孩子的右子树中,可通过左旋转达到平衡
在这两种情况下,都可以想象为结点C绕着结点N旋转。
—————————————————————————————————————————————————————————————
双旋转
右-左双旋转
图(a)是一棵AVL子树,子树T
1和T
4、T2和T3的高度相同。现将一个叶子结点插入T3,,假设插入使得T3高度加1,则以结点N为根的子树不再平衡。对结点G做一次右旋转后,以G为根的子树不平衡,则对G的左旋转恢复了树的平衡。
左-右旋转
双旋转是由进行两次单旋转来实现:
- 对结点N的孙子的旋转
- 对结点N的新孩子的旋转
可以想象为结点G是首先绕N原来的孩子C旋转,然后绕N旋转
—————————————————————————————————————————————————————————————
双旋转结论
AVL树的结点N的不平衡可以通过双旋转纠正,如果:
- 插入发生在N的右孩子的左子树中,可通过右-左双旋转达到平衡
- 插入发生在N的左孩子的右子树中,可通过左-右双旋转达到平衡
—————————————————————————————————————————————————————————————
红黑树

红黑树的特性:
- 根是黑色的
- 每个叶结点,即空结点(null)是黑的
- 红色结点的孩子都是黑点
- 从根到叶子的每条路径都含有相同数目的黑色结点
- 最长路径长度不超过最短路径长度的2倍
二叉查找树、AVL树、红黑树比较
二叉查找树:每个操作所需要的比较次数与树的高度成正比,即时间复杂度为O(log n),但随着插入结点越多,二叉查找树就会变得极不平衡,甚至会退化成链,因此最坏时达到O(n)。
为了避免二叉查找树的极端情况,于是就有了AVL树,AVL树能保证左子树和右子树的高度差不超过1。
AVL树:由于严格平衡的关系,不存在二叉查找树的极端情况。
- 查找:时间复杂度为O(log n),不会出现最坏情况
- 插入:每次插入最多只需要经过一次单旋转或双旋转,其时间复杂度为O(log n)
- 删除:每次删除最多需要O(log n)次旋转,其时间复杂度为O(2log n)
AVL树的严格平衡以牺牲插入,删除操作为代价,换来了稳定的查找时间复杂度。而红黑树即不牺牲太大的建立查找结构的代价,也能保证稳定高效的查找效率。
红黑树:由于红黑树的性质(最长路径长度不超过最短路径长度的2倍),可以说明红黑树虽然不像AVL一样是严格平衡的,但平衡性能还是要比二叉查找树要好。
- 查找:时间复杂度基本维持在O(log n),最差是要比O(log n)略大
- 插入:每次插入要经过旋转操作(最多2次)和变色操作(算法简单,代价小),时间复杂度基本在O(log n)左右
- 删除:每次删除最多需要3次旋转,比AVL树好多了,时间复杂度基本在O(log n)左右