二叉搜索樹雖然可以縮短查找的效率,但如果數據有序或接近有序二叉搜索樹將退化爲單支樹,查找元素相當於在順序表中搜索元素,效率低下
當向二叉搜索樹中插入新結點後,如果能保證每個結點的左右子樹高度之 差的絕對值不超過1(需要對樹中的結點進行調整),即可降低樹的高度,從而減少平均搜索長度。
一棵AVL樹或者是空樹,或者是具有以下性質的二叉搜索樹
- 它的左右子樹都是AVL樹
- 左右子樹高度之差(簡稱平衡因子)的絕對值不能超過1(-1/0/1)
AVL樹節點的定義
template <class T>
struct AVLTreeNode
{
AVLTreeNode(const T& val = T())
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _data(val)
, _bf(0)
{}
AVLNode<T>* _left;
AVLNode<T>* _right;
AVLNode<T>* _parent;
T _data;
int _bf;
};
與二叉搜索樹一樣插入元素
if (_root == nullptr)
{
_root = new Node(val);
return true;
}
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
if (val > cur->_data)
{
parent = cur;
cur = cur->_right;
}
else if (val < cur->_data)
{
parent = cur;
cur = cur->_left;
}
else
return false;
}
cur = new Node(val);
if (parent->_data>cur->_data)
parent->_left = cur;
else
parent->_right = cur;
cur->_parent = parent;
調節平衡因子
while (parent)
{
//更新平衡因子
if (parent->_left == cur)
--parent->_bf;
else
++parent->_bf;
if (parent->_bf == 0)
break;
else if (parent->_bf == 1 || parent->_bf == -1)
{
//繼續向上更新
cur = parent;
parent = parent->_parent;
}
else if (parent->_bf = -2 || parent->_bf == 2)
{
//旋轉
if (parent->_bf == -2 && cur->_bf == -1)
{
//右旋
RotateR(parent);
}
else if (parent->_bf == 2 && cur->_bf == 1)
{
//左旋
RotateL(parent);
}
else if (parent->_bf == 2 && cur->_bf == -1)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
int bf = subRL->_bf;
RotateR(subR);
RotateL(parent);
if (bf == -1)
{
parent->_bf = 0;
subR->_bf = 1;
}
else if (bf == 1)
{
parent->_bf = -1;
subR->_bf = 0;
}
}
else if (parent->_bf == -2 && cur->_bf == 1)
{
RotateL(cur);
RotateR(parent);
}
break;
}
左旋情況
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
subR->_left = parent;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
if (parent != _root)
{
Node* gParent = parent->_parent;
if (gParent->_left == parent)
gParent->_left = subR;
else
gParent->_right = subR;
subR->_parent = gParent;
}
else
{
subR->_parent = nullptr;
_root = subR;
}
parent->_parent = subR;
subR->_bf = parent->_bf = 0;
}
右旋情況
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
//單向鏈接 subL , parent, subLR
subL->_right = parent;
parent->_left = subLR;
//向上鏈接subLR
if (subLR)
subLR->_parent = parent;
//subL,parent->parent 雙向鏈接
if (parent != _root)
{
Node* gParent = parent->_parent;
if (gParent->_left == parent)
gParent->_left = subL;
else
gParent->_right = subL;
subL->_parent = gParent;
}
else
{
_root = subL;
subL->_parent = nullptr;
}
//向上鏈接parent, subL
parent->_parent = subL;
//更新平衡因子
subL->_bf = parent->_bf = 0;
}
判斷是否平衡
//判斷是否平衡
bool IsBalance()
{
return _IsBalance(_root);
}
bool _IsBalance(Node* root)
{
if (root == nullptr)
return true;
int left = Height(root->_left);
int right = Height(root->_right);
if (root->_bf != right - left)
{
cout << "節點:" << root->_data << "異常" << endl;
return false;
}
return abs(root->_bf) < 2 && _IsBalance(root->_left)
&& _IsBalance(root->_right);
}
深度判斷
int Height(Node* root)
{
if (root == nullptr)
return 0;
int left = Height(root->_left);
int right = Height(root->_right);
return left > right ? left + 1 : right + 1;
}
代碼整合
#include <iostream>
#include <stdlib.h>
using namespace std;
template <class T>
struct AVLNode
{
AVLNode(const T& val = T())
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _data(val)
, _bf(0)
{}
AVLNode<T>* _left;
AVLNode<T>* _right;
AVLNode<T>* _parent;
T _data;
int _bf;
};
template <class T>
class AVLTree
{
public:
typedef AVLNode<T> Node;
bool Insert(const T& val)
{
if (_root == nullptr)
{
_root = new Node(val);
return true;
}
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
if (val > cur->_data)
{
parent = cur;
cur = cur->_right;
}
else if (val < cur->_data)
{
parent = cur;
cur = cur->_left;
}
else
return false;
}
cur = new Node(val);
if (parent->_data>cur->_data)
parent->_left = cur;
else
parent->_right = cur;
cur->_parent = parent;
//調平衡
while (parent)
{
//更新平衡因子
if (parent->_left == cur)
--parent->_bf;
else
++parent->_bf;
if (parent->_bf == 0)
break;
else if (parent->_bf == 1 || parent->_bf == -1)
{
//繼續向上更新
cur = parent;
parent = parent->_parent;
}
else if (parent->_bf = -2 || parent->_bf == 2)
{
//旋轉
if (parent->_bf == -2 && cur->_bf == -1)
{
//右旋
RotateR(parent);
}
else if (parent->_bf == 2 && cur->_bf == 1)
{
//左旋
RotateL(parent);
}
else if (parent->_bf == 2 && cur->_bf == -1)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
int bf = subRL->_bf;
RotateR(subR);
RotateL(parent);
if (bf == -1)
{
parent->_bf = 0;
subR->_bf = 1;
}
else if (bf == 1)
{
parent->_bf = -1;
subR->_bf = 0;
}
}
else if (parent->_bf == -2 && cur->_bf == 1)
{
RotateL(cur);
RotateR(parent);
}
break;
}
}
return true;
}
//左旋
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
subR->_left = parent;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
if (parent != _root)
{
Node* gParent = parent->_parent;
if (gParent->_left == parent)
gParent->_left = subR;
else
gParent->_right = subR;
subR->_parent = gParent;
}
else
{
subR->_parent = nullptr;
_root = subR;
}
parent->_parent = subR;
subR->_bf = parent->_bf = 0;
}
//右旋
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
//單向鏈接 subL , parent, subLR
subL->_right = parent;
parent->_left = subLR;
//向上鏈接subLR
if (subLR)
subLR->_parent = parent;
//subL,parent->parent 雙向鏈接
if (parent != _root)
{
Node* gParent = parent->_parent;
if (gParent->_left == parent)
gParent->_left = subL;
else
gParent->_right = subL;
subL->_parent = gParent;
}
else
{
_root = subL;
subL->_parent = nullptr;
}
//向上鏈接parent, subL
parent->_parent = subL;
//更新平衡因子
subL->_bf = parent->_bf = 0;
}
//判斷是否平衡
bool IsBalance()
{
return _IsBalance(_root);
}
void InOrdre()
{
_Inorder(_root);
cout << endl;
}
void _Inorder(Node* root)
{
if (root)
{
_Inorder(root->_left);
cout << root->_data << " ";
_Inorder(root->_right);
}
}
int Height(Node* root)
{
if (root == nullptr)
return 0;
int left = Height(root->_left);
int right = Height(root->_right);
return left > right ? left + 1 : right + 1;
}
bool _IsBalance(Node* root)
{
if (root == nullptr)
return true;
int left = Height(root->_left);
int right = Height(root->_right);
if (root->_bf != right - left)
{
cout << "節點:" << root->_data << "異常" << endl;
return false;
}
return abs(root->_bf) < 2 && _IsBalance(root->_left)
&& _IsBalance(root->_right);
}
private:
Node* _root = nullptr;
};
int main()
{
AVLTree<int> avlt;
int arr[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
for (const auto& e : arr)
{
avlt.Insert(e);
cout << avlt.IsBalance() << endl;
}
avlt.InOrdre();
cout << avlt.IsBalance() << endl;
system("pause");
return 0;
}