AVL樹———又稱平衡二叉樹
二插搜索樹雖然可以縮短查找效率,但如果數據有序或接近有序二插搜索樹將退化爲單支樹,查找元素相當於在順序表中搜索元素,效率低下。
AVL樹概念:
平衡化旋轉
如果在一棵原本是平衡的二插搜索樹中插入一個新節點,可能造成不平衡,此時必須調整輸的結構,使之平衡化。
1.左單旋:
插入點位於ptr的右子結點的右子樹—-右右
2.右單旋:
插入點位於ptr的左子結點的左子樹—-左左
3.先左後右雙旋:
插入點位於ptr左子節點的右子樹—-左右
4.先右後左雙旋:
插入點位於ptr右子節點的左子樹—-右左
AVL樹的插入
AVL樹的刪除
AVL樹代碼:
【AVLTree.h】
#pragma once
#include<iostream>
using namespace std;
template<class K,class V>
struct AVLNode
{
AVLNode(K key,V value)
:_Lchild(NULL)
, _Rchild(NULL)
, _parent(NULL)
, _key(key)
, _value(value)
, _bf(0)
{}
AVLNode<K, V>* _Lchild;
AVLNode<K, V>* _Rchild;
AVLNode<K, V>* _parent;
K _key;
V _value;
int _bf;
};
template<class K,class V>
class AVLTree
{
typedef AVLNode<K, V>* pNode;
typedef AVLNode<K, V> Node;
public:
AVLTree()
:Root(NULL)
{}
bool Insert(K& k,V& v) //插入元素
{
return _Insert(k, v);
}
void InOrder() //中序遍歷
{
_InOrder(Root);
}
bool CheckAVLT() //判斷是否是AVL樹
{
return _CheckAVLT(Root);
}
/////////////////////////////////////////////////////////////
private:
bool _CheckAVLT(pNode pRoot)
{
if (pRoot)
{
int len = _Height(pRoot->_Rchild) - _Height(pRoot->_Lchild);
if (len<-1 || len>1)
return false;
_CheckAVLT(pRoot->_Lchild);
_CheckAVLT(pRoot->_Rchild);
}
return true;
}
int _Height(pNode pRoot)
{
if (pRoot == NULL)
return 0;
return _Height(pRoot->_Lchild) > _Height(pRoot->_Rchild) ? _Height(pRoot->_Lchild) + 1 : _Height(pRoot->_Rchild) + 1;
}
void _InOrder(pNode pRoot)
{
if (pRoot != NULL)
{
_InOrder(pRoot->_Lchild);
cout << "<" << pRoot->_key << "," << pRoot->_value << ">" << endl;
_InOrder(pRoot->_Rchild);
}
}
bool _Insert(K& k, V& v)
{
pNode newNode = new Node(k, v);
if (Root == NULL)
{
Root = newNode;
return true;
}
pNode cur = Root;
pNode pParent = NULL;
while (cur) //查找要插入的位置
{
pParent = cur;
if (cur->_key > k)
cur = cur->_Lchild;
else if (cur->_key < k)
cur = cur->_Rchild;
else
return false;
}
if (pParent->_key>k)
{
pParent->_Lchild = newNode;
newNode->_parent = pParent;
}
else if (pParent->_key < k)
{
pParent->_Rchild = newNode;
newNode->_parent = pParent;
}
cur = newNode; //cur標記雙親節點的孩子
while (pParent)
{
if (pParent->_Lchild == cur)
pParent->_bf--;
else if (pParent->_Rchild == cur)
pParent->_bf++;
if (pParent->_bf == 1 || pParent->_bf == -1)
{
cur = pParent;
pParent = pParent->_parent;
}
else if (pParent->_bf == 2 || pParent->_bf == -2) //旋轉
{
if (pParent->_bf == 2)
{
if (pParent->_Rchild->_bf==1)
RotateL(pParent); //左單旋
else
RotateRL(pParent); //右左雙旋
}
else
{
if (pParent->_Lchild->_bf == -1)
RotateR(pParent); //右單旋
else
RotateLR(pParent); //左右雙旋
}
}
else
break;
}
return true;
}
void RotateL(pNode pParent) //左單旋
{
pNode pSubR = pParent->_Rchild;
pNode pSubRL = pSubR->_Lchild;
pNode _pParent = pParent->_parent;
pParent->_Rchild = pSubRL;
if (pSubRL!=NULL)
pSubRL->_parent = pParent;
pSubR->_Lchild = pParent;
pParent->_parent = pSubR;
if (_pParent == NULL)
{
Root = pSubR;
pSubR->_parent = _pParent;
}
else if (_pParent != NULL&&_pParent->_Lchild == pParent)
{
_pParent->_Lchild = pSubR;
pSubR->_parent = _pParent;
}
else if (_pParent != NULL&&_pParent->_Rchild == pParent)
{
_pParent->_Rchild = pSubR;
pSubR->_parent = _pParent;
}
pSubR->_bf = 0;
pParent->_bf = 0;
}
void RotateR(pNode pParent) //右單旋
{
pNode pSubL = pParent->_Lchild;
pNode pSubLR = pSubL->_Rchild;
pNode _pParent = pParent->_parent;
pParent->_Lchild = pSubLR;
if (pSubLR!=NULL)
pSubLR->_parent = pParent;
pSubL->_Rchild = pParent;
pParent->_parent = pSubL;
if (_pParent == NULL)
{
Root = pSubL;
pSubL->_parent = _pParent;
}
else if (_pParent != NULL&&_pParent->_Lchild == pParent)
{
_pParent->_Lchild = pSubL;
pSubL->_parent = _pParent;
}
else if (_pParent != NULL&&_pParent->_Rchild == pParent)
{
_pParent->_Rchild = pSubL;
pSubL->_parent = _pParent;
}
pSubL->_bf = 0;
pParent->_bf = 0;
}
void RotateRL(pNode pnode) //右左雙旋
{
pNode pParent = pnode;
pNode pSubR = pnode->_Rchild;
RotateR(pnode->_Rchild);
RotateL(pnode);
if (pSubR->_Lchild->_bf== 1)
{
pParent->_bf = -1;
}
else if (pSubR->_Lchild->_bf == -1)
{
pSubR->_bf = 1;
}
}
void RotateLR(pNode pnode) //左右雙旋
{
pNode pParent = pnode;
pNode pSubL= pnode->_Lchild;
RotateL(pnode->_Lchild);
RotateR(pnode);
if (pSubL->_Rchild->_bf == -1)
{
pParent->_bf = 1;
}
else if (pSubL->_Rchild->_bf == 1)
{
pSubL->_bf = -1;
}
}
private:
pNode Root;
};
void test()
{
//int arr[] = {5,3,4,1,7,8,2,6,0,9}; //普通版
//int arr[] = {30,20,50,40,60,70}; //左單旋
//int arr[] = {60,40,70,30,50,20}; //右單旋
//int arr[] = { 3, 2, 6, 5, 4, 7 }; //右左雙旋
int arr[] = {4,2,6,1,3,5,15,7,16,14}; //左右雙旋
int size = sizeof(arr) / sizeof(arr[0]);
AVLTree<int, int> t;
for (int i = 0; i < size; i++)
{
t.Insert(arr[i], i);
}
t.InOrder();
if (t.CheckAVLT())
cout << "是平衡二叉樹" << endl;
else
cout << "不是平衡二叉樹" << endl;
}
【test.cpp】
#include"AVLTree.h"
int main()
{
test();
system("pause");
return 0;
}