目录
简介
AVL 树由 GM Adelson - Velsky 和 EM Landis 于 1962 年发明。该树被命名为 AVL,以纪念其发明者。AVL 树定义为高度平衡的二叉搜索树,其中每个节点都与一个平衡因子相关联,该平衡因子是通过从其左子树的高度减去其右子树的高度来计算的。
平衡系数(BF)= 左子树高度 – 右子树高度
如果每个节点的平衡因子在-1到1之间,则称树是平衡的,否则,树将不平衡,需要重新调整到平衡。
如果任一节点的平衡因子为1,则表示左子树比右子树高一级。
如果任一节点的平衡因子为0,则表示左子树和右子树的高度相等。
如果任一节点的平衡因子为-1,则表示左子树比右子树低一级。
下图给出了 AVL 树。我们可以看到,与每个节点相关的平衡因子在 -1 和 +1 之间。因此,它是 AVL 树平衡树的一个示例。
平衡的AVL树
算法时间复杂度
算法 平均情况 最差的情况
空间 O(n) O(n)
搜索 O(log n) O(log n)
插入 O(log n) O(log n)
删除 O(log n) O(log n)
AVL树上的操作
由于 AVL 树也是二叉搜索树,因此所有操作的执行方式与在二叉搜索树中执行的方式相同。搜索和遍历不会导致违反 AVL 树的属性。但是,插入和删除是可能违反此属性的操作,因此需要重新调整树。
什么情况下使用AVL树?
AVL 树通过旋转操作来控制二叉搜索树(BST)的高度。高度为 h 的二叉搜索树中所有操作所需的时间为O(h)。但是,如果 BST 树变得倾斜(即最坏情况),它的操作时间则退化到O(n)。AVL通过限制BST高度为 log n,控制每种操作的时间上限为O(log n),其中 n 是节点数。在查询操作更为频繁的情况下使用AVL树,如果插入和删除操作比较频繁的情况下,建议使用红黑树。
倾斜的二叉搜索树(BST)和单链表结构一致
AVL 旋转操作
只有在平衡因子(Balance Factor) 不是-1、0 和 1的情况下,我们才会在 AVL 树中执行旋转。
基本上有四种类型的旋转,如下所示:
RR型旋转:插入的节点在A的左子树的左子树中,RR型旋转是逆时针旋转
RR型旋转
LL型旋转:插入的节点在 A 的右子树的右子树中,LL型旋转是顺时针旋转
LL型旋转
LR型旋转:插入的节点在A的左子树的右子树中
LR型旋转
RL型旋转:插入的节点在 A 的右子树的左子树中
RL型旋转
其中节点 A 是 平衡因子不是 -1, 0, 1 的节点,红色的C为插入节点。
前两个旋转 LL 和 RR 是单旋转,接下来的两个旋转 LR 和 RL 是双旋转。对于平衡树,最小高度必须至少为 2。
下面来看稍微复制的一点的LR和RL旋转
1. LR型旋转
LR型旋转
在4节点左子树插入3节点时,5节点的BF=2,因此,5节点成为不平衡节点。3节点插入在5节点的左子树的右子树中,这种情况是 LR 型旋转,LR = RR + LL,因此首先执行以2节点为根的子树上的 RR型旋转,3节点成为2节点的右子树,在执行以5节点为根的 LL型旋转。现在每个节点的平衡因子要么是-1,要么是0,要么是1,即BST现在是平衡的。
2. RL型旋转
RL旋转
RL = LL + RR,上图中2节点为不平衡节点,4节点插入在2节点的右子树的左子树中,这种情况是 RL 型旋转,因此先执行以2节点的右子树的根节点(5节点)的LL型旋转,4节点变成5节点的左节点,在执行以2节点为根节点的RR型旋转。现在每个节点的平衡因子要么是-1,要么是0,要么是1,即BST树现在是平衡的。
代码实现(python,C++,C)
# python
from functools import reduce
import numpy as np
class TreeNode:
def __init__(self, val):
self.val = val
self.left = None
self.right = None
self.height = 1
def __str__(self):
return f"{self.val}"
class AVL_Tree:
def __init__(self):
self.root = None
self.distance = 2
self.log = []
def insert(self, key):
self.root = self._insert(self.root, key)
def _insert(self, root, key):
if not root:
return TreeNode(key)
elif key < root.val:
root.left = self._insert(root.left, key)
else:
root.right = self._insert(root.right, key)
root.height = 1 + max(self._getHeight(root.left),
self._getHeight(root.right))
balance = self._getBalance(root)
# LL旋转
if balance > 1 and key < root.left.val:
return self._rightRotate(root)
# RR旋转
if balance < -1 and key > root.right.val:
return self._leftRotate(root)
# LR旋转
if balance > 1 and key > root.left.val:
root.left = self._leftRotate(root.left)
return self._rightRotate(root)
# RL旋转
if balance < -1 and key < root.right.val:
root.right = self._rightRotate(root.right)
return self._leftRotate(root)
return root
def delete(self, key):
self._delete(self.root, key)
def _delete(self, root, key):
if not root:
return root
elif key < root.val:
root.left = self._delete(root.left, key)
elif key > root.val:
root.right = self._delete(root.right, key)
else:
if root.left is None:
temp = root.right
root = None
return temp
elif root.right is None:
temp = root.left
root = None
return temp
temp = self._getMinNode(root.right)
root.val = temp.val
root.right = self._delete(root.right, temp.val)
if root is None:
return root
root.height = 1 + max(self._getHeight(root.left),
self._getHeight(root.right))
balance = self._getBalance(root)
# LL旋转
if balance > 1 and self._getBalance(root.left) >= 0:
return self._rightRotate(root)
# RR旋转
if balance < -1 and self._getBalance(root.right) <= 0:
return self._leftRotate(root)
# LR旋转
if balance > 1 and self._getBalance(root.left) < 0:
root.left = self._leftRotate(root.left)
return self._rightRotate(root)
# RL旋转
if balance < -1 and self._getBalance(root.right) > 0:
root.right = self._rightRotate(root.right)
return self._leftRotate(root)
return root
def query(self, key):
return self._query(self.root, key)
def _query(self, root, key):
if root is None:
return None
if key == root.val:
return root
elif key < root.val:
return self._query(root.left, key)
else:
return self._query(root.right, key)
def _leftRotate(self, root):
new_root = root.right
T = new_root.left
new_root.left = root
root.right = T
root.height = 1 + max(self._getHeight(root.left),
self._getHeight(root.right))
new_root.height = 1 + max(self._getHeight(new_root.left),
self._getHeight(new_root.right))
return new_root
def _rightRotate(self, root):
new_root = root.left
T = new_root.right
new_root.right = root
root.left = T
root.height = 1 + max(self._getHeight(root.left),
self._getHeight(root.right))
new_root.height = 1 + max(self._getHeight(new_root.left),
self._getHeight(new_root.right))
return new_root
def _getMinNode(self, root):
if root is None or root.left is None:
return root
return self._getMinNode(root.left)
def _getHeight(self, root):
if not root:
return 0
return root.height
def _getBalance(self, root):
if not root:
return 0
return self._getHeight(root.left) - self._getHeight(root.right)
def _preOrder(self, root):
if not root:
return
print(f'{root.val} ', end='')
self._preOrder(root.left)
self._preOrder(root.right)
def preOrder(self):
self._preOrder(self.root)
def _print(self, node, space):
if (node == None) :
return
space += self.distance
self._print(node.right, space)
tmp = [' ' for i in range(space - self.distance)]
tmp.append(str(node.val))
self.log.append(tmp)
self._print(node.left, space)
def print(self):
self._print(self.root, 0)
max_len = reduce(max, [len(l) for l in self.log])
for i, log in enumerate(self.log):
l = len(log)
if l < max_len:
self.log[i] += ' '*(max_len - l)
self.log[i] = [c for c in self.log[i]]
logs = np.array(self.log).T
for log in logs:
print(''.join(log[::-1]))
self.log = []
avl_tree = AVL_Tree()
#for i in range(10):
# avl_tree.insert(i)
avl_tree.insert(5)
avl_tree.insert(6)
avl_tree.insert(2)
avl_tree.insert(1)
avl_tree.insert(4)
avl_tree.insert(3)
avl_tree.print()
avl_tree.delete(4)
avl_tree.print()
node = avl_tree.query(2)
if node:
print(f"query successed, value {node.val}")
// C++
#include <iostream>
using namespace std;
class TreeNode
{
public:
TreeNode(int key)
{
val = key;
left = NULL;
right = NULL;
height = 1;
}
public:
int val;
TreeNode *left;
TreeNode *right;
int height;
};
class AVL_Tree
{
public:
AVL_Tree()
{
root = NULL;
distance = 4;
}
void insert(int key)
{
root = _insert(root, key);
}
TreeNode *query(int key)
{
return _query(this->root, key);
}
void del(int key)
{
_delete(root, key);
}
void preOrder(void)
{
_preOrder(root);
}
void print(void)
{
_print(root, 0);
}
private:
TreeNode *_insert(TreeNode * root, int key)
{
if (!root)
return new TreeNode(key);
else if (key < root->val)
root->left = _insert(root->left, key);
else
root->right = _insert(root->right, key);
root->height = 1 + max(_getHeight(root->left),
_getHeight(root->right));
int balance = _getBalance(root);
// LL旋转
if (balance > 1 && key < root->left->val)
return _rightRotate(root);
// RR旋转
if (balance < -1 && key > root->right->val)
return _leftRotate(root);
// LR旋转
if (balance > 1 && key > root->left->val) {
root->left = _leftRotate(root->left);
return _rightRotate(root);
}
// RL旋转
if (balance < -1 && key < root->right->val) {
root->right = _rightRotate(root->right);
return _leftRotate(root);
}
return root;
}
TreeNode *_delete(TreeNode *root, int key)
{
if (!root)
return root;
else if (key < root->val)
root->left = _delete(root->left, key);
else if (key > root->val)
root->right = _delete(root->right, key);
else {
TreeNode *temp;
if (!root->left) {
temp = root->right;
root = NULL;
return temp;
} else if (!root->right) {
temp = root->left;
root = NULL;
return temp;
} else {
temp = _getMinNode(root->right);
root->val = temp->val;
root->right = _delete(root->right, temp->val);
}
}
if (!root)
return root;
root->height = 1 + max(_getHeight(root->left),
_getHeight(root->right));
int balance = _getBalance(root);
// LL旋转
if (balance > 1 && _getBalance(root->left) >= 0)
return _rightRotate(root);
// RR旋转
if (balance < -1 && _getBalance(root->right) <= 0)
return _leftRotate(root);
// LR旋转
if (balance > 1 && _getBalance(root->left) < 0) {
root->left = _leftRotate(root->left);
return _rightRotate(root);
}
// RL旋转
if (balance < -1 && _getBalance(root->right) > 0) {
root->right = _rightRotate(root->right);
return _leftRotate(root);
}
return root;
}
TreeNode *_query(TreeNode *root, int key)
{
if (!root)
return NULL;
if (key == root->val)
return root;
else if (key < root->val)
return _query(root->left, key);
else
return _query(root->right, key);
}
TreeNode *_leftRotate(TreeNode * root)
{
TreeNode *new_root = root->right;
TreeNode *T = new_root->left;
new_root->left = root;
root->right = T;
root->height = 1 + max(_getHeight(root->left),
_getHeight(root->right));
new_root->height = 1 + max(_getHeight(new_root->left),
_getHeight(new_root->right));
return new_root;
}
TreeNode *_rightRotate(TreeNode * root)
{
TreeNode *new_root = root->left;
TreeNode *T = new_root->right;
new_root->right = root;
root->left = T;
root->height = 1 + max(_getHeight(root->left),
_getHeight(root->right));
new_root->height = 1 + max(_getHeight(new_root->left),
_getHeight(new_root->right));
return new_root;
}
int max(int a, int b)
{
return (a > b)?a:b;
}
TreeNode *_getMinNode(TreeNode *root)
{
if (!root || !root->left)
return root;
return _getMinNode(root->left);
}
int _getHeight(TreeNode *root)
{
if (!root)
return 0;
return root->height;
}
int _getBalance(TreeNode *root)
{
if (!root)
return 0;
return _getHeight(root->left) - _getHeight(root->right);
}
void _preOrder(TreeNode *root)
{
if (!root)
return;
cout << root->val << " ";
_preOrder(root->left);
_preOrder(root->right);
}
void _print(TreeNode *node, int space)
{
if (!node)
return;
space += distance;
_print(node->right, space);
for (int i=0; i < space - distance; i++)
cout << " ";
cout << node->val << endl;
_print(node->left, space);
}
private:
TreeNode *root;
int distance;
};
int main(void)
{
AVL_Tree avl_tree = AVL_Tree();
avl_tree.insert(5);
avl_tree.insert(6);
avl_tree.insert(2);
avl_tree.insert(1);
avl_tree.insert(4);
avl_tree.insert(3);
avl_tree.print();
avl_tree.del(4);
avl_tree.print();
TreeNode *node = avl_tree.query(3);
if (node)
cout << "query successed, value " << node->val << endl;
return 0;
}
// C
#include <stdio.h>
#include <stdlib.h>
struct TreeNode
{
int val;
struct TreeNode *left;
struct TreeNode *right;
int height;
};
static const int distance = 4;
static int max(int a, int b)
{
return (a > b)?a:b;
}
static struct TreeNode *_getMinNode(struct TreeNode *root)
{
if (!root || !root->left)
return root;
return _getMinNode(root->left);
}
static int _getHeight(struct TreeNode *root)
{
if (!root)
return 0;
return root->height;
}
static int _getBalance(struct TreeNode *root)
{
if (!root)
return 0;
return _getHeight(root->left) - _getHeight(root->right);
}
static struct TreeNode *_leftRotate(struct TreeNode *root)
{
struct TreeNode *new_root = root->right;
struct TreeNode *T = new_root->left;
new_root->left = root;
root->right = T;
root->height = 1 + max(_getHeight(root->left),
_getHeight(root->right));
new_root->height = 1 + max(_getHeight(new_root->left),
_getHeight(new_root->right));
return new_root;
}
static struct TreeNode *_rightRotate(struct TreeNode *root)
{
struct TreeNode *new_root = root->left;
struct TreeNode *T = new_root->right;
new_root->right = root;
root->left = T;
root->height = 1 + max(_getHeight(root->left),
_getHeight(root->right));
new_root->height = 1 + max(_getHeight(new_root->left),
_getHeight(new_root->right));
return new_root;
}
static void _print_tree(struct TreeNode * node, int space)
{
if (!node)
return;
space += distance;
_print_tree(node->right, space);
for (int i=0; i < space - distance; i++)
printf(" ");
printf("%d\n", node->val);
_print_tree(node->left, space);
}
void print_tree(struct TreeNode * node)
{
_print_tree(node, 0);
}
void preOrder(struct TreeNode *root)
{
if (!root)
return;
printf("%d ", root->val);
preOrder(root->left);
preOrder(root->right);
}
struct TreeNode *insert(struct TreeNode *root, int key)
{
if (!root) {
struct TreeNode *node = (struct TreeNode *)malloc(sizeof(*root));
node->val = key;
node->left = NULL;
node->right = NULL;
node->height = 1;
return node;
} else if (key < root->val) {
root->left = insert(root->left, key);
} else {
root->right = insert(root->right, key);
}
root->height = 1 + max(_getHeight(root->left),
_getHeight(root->right));
int balance = _getBalance(root);
// LL旋转
if (balance > 1 && key < root->left->val)
return _rightRotate(root);
// RR旋转
if (balance < -1 && key > root->right->val)
return _leftRotate(root);
// LR旋转
if (balance > 1 && key > root->left->val) {
root->left = _leftRotate(root->left);
return _rightRotate(root);
}
// RL旋转
if (balance < -1 && key < root->right->val) {
root->right = _rightRotate(root->right);
return _leftRotate(root);
}
return root;
}
struct TreeNode *query(struct TreeNode *root, int key)
{
if (!root)
return NULL;
if (key == root->val)
return root;
else if (key < root->val)
return query(root->left, key);
else
return query(root->right, key);
}
struct TreeNode *delete(struct TreeNode *root, int key)
{
if (!root)
return root;
else if (key < root->val)
root->left = delete(root->left, key);
else if (key > root->val)
root->right = delete(root->right, key);
else {
struct TreeNode *temp;
if (!root->left) {
temp = root->right;
root = NULL;
return temp;
} else if (!root->right) {
temp = root->left;
root = NULL;
return temp;
} else {
temp = _getMinNode(root->right);
root->val = temp->val;
root->right = delete(root->right, temp->val);
}
}
if (!root)
return root;
root->height = 1 + max(_getHeight(root->left),
_getHeight(root->right));
int balance = _getBalance(root);
// LL旋转
if (balance > 1 && _getBalance(root->left) >= 0)
return _rightRotate(root);
// RR旋转
if (balance < -1 && _getBalance(root->right) <= 0)
return _leftRotate(root);
// LR旋转
if (balance > 1 && _getBalance(root->left) < 0) {
root->left = _leftRotate(root->left);
return _rightRotate(root);
}
// RL旋转
if (balance < -1 && _getBalance(root->right) > 0) {
root->right = _rightRotate(root->right);
return _leftRotate(root);
}
return root;
}
int main(void)
{
struct TreeNode *root;
root = insert(root, 5);
root = insert(root, 6);
root = insert(root, 2);
root = insert(root, 1);
root = insert(root, 4);
root = insert(root, 3);
print_tree(root);
root = delete(root, 4);
print_tree(root);
struct TreeNode *node = query(root, 3);
if (node)
printf("query successed, value %d\n", node->val);
return 0;
}