1.AVL树的概念
- AVL树
AVL树又称为高度平衡的二叉搜索树,是1962年有俄罗斯的数学家G.M.Adel’son-Vel’skii和E.M.Landis提出来的。它能保持二叉树的高度平衡,尽量降低二叉树的高度,减少树的平均搜索长度 - AVL树的性质
1.左子树和右子树的高度之差的绝对值不超过1
2.中的每个左子树和右子树都是AVL树
3.每个节点都有一个平衡因子(balance factor–bf),任一节点的平衡因子是-1,0,1。(每个节点的平衡因子等于右子树的高度减去左子树的高度 )
2.平衡化旋转
(1)左单旋转
如下图所示,a,b,c均为高度为h的子树。当插入节点d时,影响了c子树的高度及平衡因子,以及节点2的平衡因子。
此时,需要调整这棵树(左旋),使得平衡因子的绝对值小于2;
代码:
//左旋
void _RotateL(Node* parent)
{
assert(parent);
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
{
subRL->_parent = parent;
}
Node* ppNode = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
if (ppNode == NULL)
{
_root = subR;
subR->_parent = NULL;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subR;
subR->_parent = ppNode;
}
else
{
ppNode->_right = subR;
subR->_parent = ppNode;
}
}
parent->_bf = subR->_bf = 0;
}
(2)右单旋转
右旋与左旋类似,只是方向方向刚好相反。
代码:
//右旋
void _RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
{
subLR->_parent = parent;
}
Node* ppNode = parent->_parent;
subL->_right = parent;
parent->_parent = subL;
if (ppNode == NULL)
{
_root = subL;
subL->_parent = NULL;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subL;
subL->_parent = ppNode;
}
else
{
ppNode->_right = subL;
subL->_parent = ppNode;
}
}
parent->_bf = subL->_bf = 0;
}
(3)先左后右双旋转
先左后右双旋转分为三种情况
1>subLR的平衡因子为0
只有当a,b不存在且节点2为插入的节点时,才需要左右旋转。
先以节点1为轴左旋,再以节点3为轴右旋,完成旋转。
2>subLR的平衡因子为1
先以节点1为轴左旋,再以节点3为轴右旋,完成旋转。
3>subLR的平衡因子为-1
先以节点1为轴左旋,再以节点3为轴右旋,完成旋转。
旋转完成后更新平衡因子
旋转后的平衡因子如下:
subLR->_bf | parent | subL | subLR |
---|---|---|---|
0 | 0 | 0 | 0 |
1 | 0 | -1 | 0 |
-1 | 1 | 0 | 0 |
代码:
void _RotateLR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
int bf = subLR->_bf;
_RotateL(subL);
_RotateR(parent);
if (bf == 0)
{
parent->_bf = subL->_bf = subLR->_bf = 0;
}
else if (bf == 1)
{
parent->_bf = 0;
subL->_bf = -1;
subLR->_bf = 0;
}
else //bf == -1
{
parent->_bf = 1;
subL->_bf = 0;
subLR->_bf = 0;
}
}
(4)先右后左双旋转
与先左后右双旋转类似,就不详细介绍了。
代码:
void _RotateRL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
int bf = subRL->_bf;
_RotateR(parent->_right);
_RotateL(parent);
if (bf == 0)
{
parent->_bf = 0;
subR->_bf = 0;
subRL->_bf = 0;
}
else if (bf == 1)
{
parent->_bf = -1;
subR->_bf = 0;
subRL->_bf = 0;
}
else //bf == -1
{
parent->_bf = 0;
subR->_bf = 1;
subRL->_bf = 0;
}
}
3.AVL树的插入
(1)找到要插入的位置
if (_root == NULL)
{
_root = new Node(key);
return true;
}
Node* cur = _root;
Node* parent = NULL;
//找到要插入的节点的位置
while (cur)
{
if (key > cur->_key)
{
parent = cur;
cur = cur->_right;
}
else if (key < cur->_key)
{
parent = cur;
cur = cur->_left;
}
else
{
return false; //表示已经存在,就不再插入了
}
}
(2)插入节点
cur = new Node(key);
if (key > parent->_key)
{
parent->_right = cur;
cur->_parent = parent;
}
else
{
parent->_left = cur;
cur->_parent = parent;
}
(3)更新平衡因子
//更新平衡因子,分三种情况
while (parent)
{
if (parent->_left == cur)
parent->_bf--;
else
parent->_bf++;
//1.
if (parent->_bf == 0)
{
return true;
}
//2.
else if (abs(parent->_bf) == 1)
{
cur = parent;
parent = cur->_parent;
}
//3.
else //abs(parent->_bf) == 2
{
Node* subL = parent->_left;
Node* subR = parent->_right;
if (parent->_bf == -2 && subL->_bf == -1)
{
_RotateR(parent);
return true;
}
else if (parent->_bf == 2 && subR->_bf == 1)
{
_RotateL(parent);
return true;
}
else if (parent->_bf == -2 && subL->_bf == 1)
{
_RotateLR(parent);
return true;
}
else // (parent->_bf == 2 && subR->_bf == -1)
{
_RotateRL(parent);
return true;
}
}
}
4.判断一个二叉树是否AVL树
一颗二叉树为AVL,得同时满足是搜索二叉树(节点左孩子的值小于节点的值,节点右孩子的值大于节点的值)及这棵树平衡(左右子树的高度差不超过1)。
代码:
bool IsAVL()
{
if (IsBST(_root) && IsBalance(_root))
{
return true;
}
return false;
}
bool IsBST(Node* root)
{
if (root == NULL)
{
return true;
}
Node* left = root->_left;
Node* right = root->_right;
if (left && left->_key < root->_key)
{
return IsBST(root->_left);
}
else if (right && right->_key > root->_key)
{
return IsBST(root->_right);
}
}
bool IsBalance(Node* root)
{
if (root == NULL)
return true;
int rightHeight = _Height(root->_right);
int leftHeight = _Height(root->_left);
int diff = rightHeight - leftHeight;
return abs(diff) < 2 && IsBalance(root->_left) && IsBalance(root->_right);
}
int _Height(Node* node)
{
if (node == NULL)
return 0;
int right = _Height(node->_right) + 1;
int left = _Height(node->_left) + 1;
return right > left ? right : left;
}
5.完整代码:
#pragma once
#include <iostream>
#include <assert.h>
#include <stdlib.h>
using namespace std;
template <class K>
struct AVLTreeNode
{
K _key;
int _bf; //平衡因子
AVLTreeNode<K>* _left;
AVLTreeNode<K>* _right;
AVLTreeNode<K>* _parent;
AVLTreeNode(const K& key)
:_key(key)
, _bf(0)
, _left(NULL)
, _right(NULL)
, _parent(NULL)
{}
};
template <class K>
class AVLTree
{
public:
typedef AVLTreeNode<K> Node;
public:
AVLTree()
:_root(NULL)
{}
~AVLTree()
{
_Destroy(_root);
}
bool Insert(const K& key)
{
if (_root == NULL)
{
_root = new Node(key);
return true;
}
Node* cur = _root;
Node* parent = NULL;
//找到要插入的节点的位置
while (cur)
{
if (key > cur->_key)
{
parent = cur;
cur = cur->_right;
}
else if (key < cur->_key)
{
parent = cur;
cur = cur->_left;
}
else
{
return false; //表示已经存在,就不再插入了
}
}
//插入节点
cur = new Node(key);
if (key > parent->_key)
{
parent->_right = cur;
cur->_parent = parent;
}
else
{
parent->_left = cur;
cur->_parent = parent;
}
//更新平衡因子
while (parent)
{
if (parent->_left == cur)
parent->_bf--;
else
parent->_bf++;
if (parent->_bf == 0)
{
return true;
}
else if (abs(parent->_bf) == 1)
{
cur = parent;
parent = cur->_parent;
}
else //abs(parent->_bf) == 2
{
Node* subL = parent->_left;
Node* subR = parent->_right;
if (parent->_bf == -2 && subL->_bf == -1)
{
_RotateR(parent);
return true;
}
else if (parent->_bf == 2 && subR->_bf == 1)
{
_RotateL(parent);
return true;
}
else if (parent->_bf == -2 && subL->_bf == 1)
{
_RotateLR(parent);
return true;
}
else // (parent->_bf == 2 && subR->_bf == -1)
{
_RotateRL(parent);
return true;
}
}
}
return true;
}
void InOrder()//中序遍历
{
_InOrder(_root);
cout << endl;
}
bool IsAVL()
{
if (IsBST(_root) && IsBalance(_root))
{
return true;
}
return false;
}
protected:
bool IsBST(Node* root)
{
if (root == NULL)
{
return true;
}
Node* left = root->_left;
Node* right = root->_right;
if (left && left->_key < root->_key)
{
return IsBST(root->_left);
}
else if (right && right->_key > root->_key)
{
return IsBST(root->_right);
}
}
bool IsBalance(Node* root)
{
if (root == NULL)
return true;
int rightHeight = _Height(root->_right);
int leftHeight = _Height(root->_left);
int diff = rightHeight - leftHeight;
return abs(diff) < 2 && IsBalance(root->_left) && IsBalance(root->_right);
}
int _Height(Node* node)
{
if (node == NULL)
return 0;
int right = _Height(node->_right) + 1;
int left = _Height(node->_left) + 1;
return right > left ? right : left;
}
void _InOrder(Node* root)
{
if (root != NULL)
{
_InOrder(root->_left);
cout << root->_key << " ";
_InOrder(root->_right);
}
}
//左旋
void _RotateL(Node* parent)
{
assert(parent);
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
{
subRL->_parent = parent;
}
Node* ppNode = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
if (ppNode == NULL)
{
_root = subR;
subR->_parent = NULL;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subR;
subR->_parent = ppNode;
}
else
{
ppNode->_right = subR;
subR->_parent = ppNode;
}
}
parent->_bf = subR->_bf = 0;
}
//右旋
void _RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
{
subLR->_parent = parent;
}
Node* ppNode = parent->_parent;
subL->_right = parent;
parent->_parent = subL;
if (ppNode == NULL)
{
_root = subL;
subL->_parent = NULL;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subL;
subL->_parent = ppNode;
}
else
{
ppNode->_right = subL;
subL->_parent = ppNode;
}
}
parent->_bf = subL->_bf = 0;
}
void _RotateLR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
int bf = subLR->_bf;
_RotateL(subL);
_RotateR(parent);
if (bf == 0)
{
parent->_bf = subL->_bf = subLR->_bf = 0;
}
else if (bf == 1)
{
parent->_bf = 0;
subL->_bf = -1;
subLR->_bf = 0;
}
else //bf == -1
{
parent->_bf = 1;
subL->_bf = 0;
subLR->_bf = 0;
}
}
void _RotateRL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
int bf = subRL->_bf;
_RotateR(parent->_right);
_RotateL(parent);
if (bf == 0)
{
parent->_bf = 0;
subR->_bf = 0;
subRL->_bf = 0;
}
else if (bf == 1)
{
parent->_bf = -1;
subR->_bf = 0;
subRL->_bf = 0;
}
else //bf == -1
{
parent->_bf = 0;
subR->_bf = 1;
subRL->_bf = 0;
}
}
void _Destroy(Node* root)
{
if (root == NULL)
return;
_Destroy(root->_left);
_Destroy(root->_right);
delete root;
root = NULL;
}
protected:
Node* _root;
};
void TestAVLTree()
{
/*int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };*/
int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
int size = sizeof(a) / sizeof(a[0]);
AVLTree<int> a1;
for (int i = 0; i < size; i++)
{
a1.Insert(a[i]);
cout << a[i]<<"IsAVL:" << a1.IsAVL() << endl;
}
a1.InOrder();
cout << "IsAVL:" << a1.IsAVL() << endl;
}