AVL tree是一个“加上了额外平衡条件”的二叉搜索树。其平衡条件的建立是为了确保整棵树的深度为O(logN)。平衡二叉搜索树的大部分实现与普通的二叉搜索树相同,区别在于插入和删除节点之后需要对节点做一个旋转操作来维持平衡。
侯捷先生在STL源码剖析中提到,直观上的最佳平衡条件是每个节点的左右子树有着相同的高度,但这也未免太过严苛,我们很难插入新元素而又保持这样的平衡条件。AVL tree于是退而求其次,要求任何节点的左右子树高度相差最多1。
对二叉树的平衡调整过程,主要包含四种旋转操作:LL,LR,RR,RL 。
LL(左左):插入点位于 X 的左子节点的左子树
LR(左右):插入点位于 X 的左子节点的右子树
RR(右右):插入点位于 X 的右子节点的右子树
RL(右左):插入点位于 X 的右子节点的左子树
下面是AVL平衡二叉树的代码实现:
#include
#include
#include
using namespace std;
struct AVLTreeNode {
int val;
AVLTreeNode* left;
AVLTreeNode* right;
int height; //子树的高度
};
void makeEmpty(AVLTreeNode* T) {
if (T == NULL)
return;
else {
makeEmpty(T->left);
makeEmpty(T->right);
delete(T);
}
}
int _Height(AVLTreeNode* T) {
if (T == NULL)
return 0;
else
return T->height;
}
int _Max(int n1, int n2) {
return n1 > n2 ? n1 : n2;
}
//LL == 右旋转
AVLTreeNode* single_rotate_LL(AVLTreeNode* k2) {
AVLTreeNode* k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
k2->height = _Max(_Height(k2->left), _Height(k2->right)) + 1;
k1->height = _Max(_Height(k1->left), k2->height) + 1;
return k1;
}
//RR == 左旋转
AVLTreeNode* single_rotate_RR(AVLTreeNode* k1) {
AVLTreeNode* k2 = k1->right;
k1->right = k2->left;
k2->left = k1;
k1->height = _Max(_Height(k1->left), _Height(k1->right)) + 1;
k2->height = _Max(k1->height, _Height(k2->right)) + 1;
return k2;
}
//LR == 先将 k3 的左子节点进行左旋转,再对 k3 右旋转
AVLTreeNode* double_rotate_LR(AVLTreeNode* k3) {
k3->left = single_rotate_RR(k3->left);
return single_rotate_LL(k3);
}
//RL == 先将 k3 的右子节点进行右旋转,再对 k3 左旋转
AVLTreeNode* double_rotate_RL(AVLTreeNode* k4) {
k4->right = single_rotate_LL(k4->right);
return single_rotate_RR(k4);
}
AVLTreeNode* AVL_insert(AVLTreeNode* T, int value) {
if (T == NULL) {
T = new AVLTreeNode;
if (T == NULL) {
cout << "ERROR: creat AVL node failed !" << endl;
return NULL;
}
T->val = value;
T->left = NULL;
T->right = NULL;
T->height = 0;
}
else if (value < T->val) {
T->left = AVL_insert(T->left, value);
//插入元素之后,若 T 的左子树比右子树高度 之差是 2,即不满足 AVL平衡特性,需要调整
if (_Height(T->left) - _Height(T->right) == 2) {
if (value < T->left->val)
T = single_rotate_LL(T); //把x插入到了T->left的左侧,只需 左侧单旋转 -- LL旋转
else
T = double_rotate_LR(T); // x 插入到了T->left的右侧,需要左侧双旋转
}
}
else if (value > T->val) {
T->right = AVL_insert(T->right, value);
if (_Height(T->right) - _Height(T->left) == 2) {
if (value > T->right->val)
T = single_rotate_RR(T);
else
T = double_rotate_RL(T);
}
}
else if (value == T->val) {
cout << "添加失败,不能添加相同的节点" << endl;
}
T->height = _Max(_Height(T->left), _Height(T->right)) + 1;
return T;
}
//对单个节点进行的AVL调整
AVLTreeNode* AVL_balance(AVLTreeNode* T) {
if (_Height(T->left) - _Height(T->right) == 2) {
if (_Height(T->left->left) >= _Height(T->left->right))
T = single_rotate_LL(T);
else
T = double_rotate_LR(T);
}
if (_Height(T->right) - _Height(T->left) == 2) {
if (_Height(T->right->right) >= _Height(T->right->left))
T = single_rotate_RR(T);
else
T = double_rotate_RL(T);
}
return T;
}
/**
* 首先定位要删除的节点,然后用该节点的右孩子的最左孩子替换该节点,
* 并重新调整以该节点为根的子树为AVL树,具体调整方法跟插入数据类似
* 删除处理在整体上耗费O(log n) 时间。
*/
AVLTreeNode* AVL_delete(AVLTreeNode* T, int value) {
if (T == NULL)
return NULL;
else if (value < T->val)
T->left = AVL_delete(T->left, value);
else if (value > T->val)
T->right = AVL_delete(T->right, value);
else if (value == T->val) {
if (T->right == NULL) {
AVLTreeNode* temp = T->left;
//T = T->left;
//T = (T->left != NULL) ? T->left : T->right;
delete T;
return temp;
}
else {
AVLTreeNode* temp = T->right;
while (temp->left) {
temp = temp->left;
}
T->val = temp->val;
T->right = AVL_delete(T->right, T->val);
//T->height = _Max(_Height(T->left), _Height(T->right)) + 1;
}
return T;
}
//当删除元素后调整平衡
if (T->left != NULL)
T->left = AVL_balance(T->left);
if (T->right != NULL)
T->right = AVL_balance(T->right);
if (T != NULL)
T = AVL_balance(T);
T->height = _Max(_Height(T->left), _Height(T->right)) + 1;
return T;
}
void inOrder(AVLTreeNode* T) {
if (T == NULL)
return;
stack
s;
AVLTreeNode* node = T;
while (node != NULL || !s.empty()) {
while (node != NULL) {
s.push(node);
node = node->left;
}
node = s.top();
cout << node->val << " ";
s.pop();
if (node->right == NULL)
node = NULL;
else
node = node->right;
}
cout << endl;
}
int main() {
AVLTreeNode* T = NULL;
int a[] = { 3, 2, 1, 4, 5, 6, 7, 16, 15, 14, 13, 12, 11, 10, 8, 9 };
for (int i = 0; i < 16; i++) {
T = AVL_insert(T, a[i]);
}
preOrder(T);
inOrder(T);
postOrder(T);
AVLTreeNode* temp;
temp = AVL_delete(T, 7);
inOrder(temp);
return 0;
}