AVL樹
AVL樹又稱為高度平衡的二叉搜索樹,它能保持二叉樹的高度平衡,盡量降低二叉樹的高度,減少樹的平均搜索長度;
AVL樹的性質
左子樹和右子樹的高度之差的絕對值不超過1
樹中的每個左子樹和右子樹都是AVL樹
下面實現一棵AVL樹,主要實現其插入部分:
#pragma once
template <class K, class V>
struct AVLTreeNode
{
K _key;
V _val;
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent;
int _bf;//平衡因子
AVLTreeNode(const K& key, const K& val)
:_key(key)
,_val(val)
,_left(NULL)
,_right(NULL)
,_parent(NULL)
,_bf(0)
{}
};
template <class K, class V>
class AVLTree
{
typedef AVLTreeNode<K, V> Node;
public:
AVLTree()
:_root(NULL)
{}
~AVLTree()
{
_Clear(_root);
}
bool Insert(const K& key, const V& val)
{
if(_root == NULL)//如果根結點為NULL,則創建一個結點,返回真
{
_root = new Node(key, val);
return true;
}
Node* cur = _root;
Node* prev = NULL;
while(cur != NULL)//查找合適的位置插入
{
if(cur->_key == key)//如果結點已存在,則返回假
return false;
else if(cur->_key > key)//如果要插入值小于當前結點,則去左子樹查找
{
prev = cur;
cur = cur->_left;
}
else//如果插入值大于當前結點,則去右子樹查找
{
prev = cur;
cur = cur->_right;
}
}
//循環結束,則表明找到了合適的位置,判斷應插入左邊還是右邊
Node* tmp = new Node(key, val);
if(key < prev->_key)
prev->_left = tmp;
else
prev->_right = tmp;
tmp->_parent = prev;
//插入結點之后,需要判斷當前樹是否滿足AVL樹的規則,若不滿足,進行相應的調整
while(prev != NULL)
{
//平衡因子為右邊高度減去左邊高度
if(prev->_left == tmp)
--(prev->_bf);
else
++(prev->_bf);
if(prev->_bf == 0)//如果平衡因子為0,則一定平衡,因為可以看做是在同一層插入了一個結點,對高度并無影響
break;
else if(prev->_bf == 1 || prev->_bf == -1)//如果平衡因子為1/-1,則表明高度有所變化,需要繼續向上調整
{
tmp = prev;
prev = prev->_parent;
}
else//說明平衡因子的絕對值大于1,則這個時候不滿足AVL樹的性質,需要進行調整
{
if(prev->_bf == 2)
{
if(tmp->_bf == 1)
_RotateL(prev);
else
{
_RotateR(tmp);
_RotateL(prev);
}
}
else
{
if(tmp->_bf == -1)
_RotateR(prev);
else
{
_RotateL(tmp);
_RotateR(prev);
}
}
break;
}
}
return true;
}
void InOrder()
{
_InOrder(_root);
cout<<endl;
}
protected:
void _Clear(Node* root)
{
if(root != NULL)
{
_Clear(root->_left);
_Clear(root->_right);
delete root;
root = NULL;
}
}
//左單旋
void _RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if(subRL != NULL)
subRL->_parent = parent;
subR->_left = parent;
Node* ppNode = parent->_parent;
parent->_parent = subR;
if(ppNode == NULL)
_root = subR;
else
{
if(ppNode->_left == parent)
ppNode->_left = subR;
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 != NULL)
subLR->_parent = parent;
subL->_right = parent;
Node* ppNode = parent->_parent;
parent->_parent = subL;
if(ppNode == NULL)
_root = subL;
else
{
if(ppNode->_left == parent)
ppNode->_left = subL;
else
ppNode->_right = subL;
}
subL->_parent = ppNode;
parent->_bf = subL->_bf = 0;
}
void _InOrder(Node* root)
{
if(root != NULL)
{
_InOrder(root->_left);
cout<<root->_key<<" ";
_InOrder(root->_right);
}
}
protected:
Node* _root;
};
void Test()
{
int arr[] = {4, 2, 6, 1, 3, 5, 15, 7, 16, 14};
//int arr[] = {16, 3, 7, 11, 9, 26, 18, 14, 15};
AVLTree<int, int> t;
for(int i = 0; i < sizeof(arr)/sizeof(arr[0]); ++i)
t.Insert(arr[i], i);
t.InOrder();
}其中的左右單旋如下圖所示:


運行程序:


《完》
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。