您的位置:首页 > 理论基础 > 数据结构算法

【数据结构】搜索结构之AVL树

2018-03-05 22:06 169 查看
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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: