您的位置:首页 > 其它

平衡二叉树

2016-07-06 21:20 477 查看
介绍:

AVL树也就是平衡二叉树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。

平衡因子:

节点的平衡因子是它的右子树的高度减去它的左子树的高度(有时相反)。带有平衡因子1、0或 -1的节点被认为是平衡的。带有平衡因子 -2或2的节点被认为是不平衡的,并需要重新平衡这个树。平衡因子可以直接存储在每个节点中,或从可能存储在节点中的子树高度计算出来。

操作:

AVL树的基本操作一般涉及运作同在不平衡的二叉查找树所运作的同样的算法。但是要进行预先或随后做一次或多次所谓的”AVL旋转”。

实现描述:

假设平衡因子是右子树的高度减去左子树的高度所得到的值,又假设由于在二叉排序树上插入节点而失去平衡的最小子树根节点的指针为a(即a是离插入点最近,且平衡因子绝对值超过1的祖先节点),则失去平衡后进行的规律可归纳为下列四种情况:

单向右旋平衡处理LL:由于在*a的左子树根节点的左子树上插入节点,*a的平衡因子由1增至2,致使以*a为根的子树失去平衡,则需进行一次右旋转操作;

单向左旋平衡处理RR:由于在*a的右子树根节点的右子树上插入节点,*a的平衡因子由-1变为-2,致使以*a为根的子树失去平衡,则需进行一次左旋转操作;

双向旋转(先左后右)平衡处理LR:由于在*a的左子树根节点的右子树上插入节点,*a的平衡因子由1增至2,致使以*a为根的子树失去平衡,则需进行两次旋转(先左旋后右旋)操作。

双向旋转(先右后左)平衡处理RL:由于在*a的右子树根节点的左子树上插入节点,*a的平衡因子由-1变为-2,致使以*a为根的子树失去平衡,则需进行两次旋转(先右旋后左旋)操作

下面以插入一组数为例做详细介绍:

如插入数据{16, 3, 7, 11, 9, 26, 18, 14, 15}

平衡之后的图为:



先插入16和3,插入之后为:



插入7:

插入没调节如下图:



此时已经不满足平衡:

调节之后为:



插入11:



此时平衡不需要调节

插入9:



可以看出此时已经不平衡,需要调节

右旋调节之后为:



可以看出平衡了

插入26:



此时不平衡。

需要左旋:

调节之后为:



插入18:



此时不平衡。

调节之后为:



插入14:



平衡,不用调节。

插入15:



此时不平衡。

调节之后为:



代码:

#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
template<class K,class V>
struct AVLTreeNode
{
K _key;
V _value;
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent;
int _bf;  //平衡因子 可以是 0 1 -1
AVLTreeNode(const K& key, const V& value)
:_key(key),
_value(value),
_left(NULL),
_right(NULL),
_parent(NULL),
_bf(0)
{}
};

template<class K,class V>
class AVLTree
{
typedef AVLTreeNode<K, V> Node;
public:
AVLTree()
:_root(NULL)
{}

bool Insert(const K& key, const V& value)
{
if (_root == NULL)
{
_root = new Node(key, value);
return true;
}
Node* cur = _root;
Node* parent = NULL;
/*查找插入的位置*/
while (cur)
{
if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else
{
return false;
}
}
Node* tmp = new Node(key, value);  //插入数据
if (parent->_key > key)
{
parent->_left = tmp;
tmp->_parent = parent;
}
else
{
parent->_right = tmp;
tmp->_parent = parent;
}
//调节平衡因子
cur = tmp;
bool isRotate = false;
/*查看需不需要调节*/
while (parent)
{
/*变换parent的平衡因子*/
if (parent->_left == cur)
{
parent->_bf--;
}
else
{
parent->_bf++;
}
if (parent->_bf == 0)//一定是由1或-1变得,不会影响上层
{
break;
}
else if (parent->_bf == 1 || parent->_bf == -1) //继续上调
{
cur = parent;
parent=cur->_parent;
}

/*进行旋转*/
else//已经不平衡了
{
if (parent->_bf == 2)
{
if (cur->_bf == 1)
{
_RotateL(parent);
}
else // -1
{
_RotateRL(parent);
}
}
else // -2
{
if (cur->_bf == -1)
{
_RotateR(parent);
}
else // 1
{
_RotateLR(parent);
}
}

isRotate = true;
break;
}
}
if (isRotate)
{
Node* ppNode = parent->_parent;
if (ppNode == NULL)
_root = parent;
else if (ppNode->_key > parent->_key)
ppNode->_left = parent;
else
ppNode->_right = parent;
}

return true;
}

void InOrder()
{
_InOrder(_root);
}

bool IsBlance()
{
return _IsBlance(_root);
}

protected:
int _Height(Node* root)
{
if (root == NULL)
{
return 0;
}
int left=_Height(root->_left);
int right=_Height(root->_right);
return left > right ? left + 1 : right + 1;
}
bool _IsBlance(Node* root)
{
if (root == NULL)
{
return true;
}
int bf = _Height(root->_right) - _Height(root->_left);
//assert(bf == root->_bf);

if (bf != root->_bf)
{
cout << "平衡因子异常:" << root->_key << endl;
}

return bf == root->_bf && abs(bf) < 2;

}
void _InOrder(Node* root)
{
if (root == NULL)
{
return;
}
_InOrder(root->_left);
cout << root->_key << " ";
_InOrder(root->_right);
}
void _RotateL(Node*& parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
{
subRL->_parent = parent;
}
subR->_left = parent;
subR->_parent = parent->_parent;
parent->_parent = subR;
parent->_bf = subR->_bf = 0;
parent = subR;
}

void _RotateR(Node*& parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
{
subLR->_parent = parent;
}
subL->_right = parent;
subL->_parent = parent->_parent;
parent->_parent = subL;
parent->_bf = subL->_bf = 0;
parent = subL;
}

void _RotateLR(Node* parent)
{
Node* pNode = parent;
Node* subL = parent->_left;
Node* subLR = subL->_right;
int bf = subLR->_bf;
_RotateL(parent->_left);
_RotateR(parent);

if (bf == -1)
{
subL->_bf = 0;
pNode->_bf = 1;
}
else if (bf == 1)
{
subL->_bf = -1;
pNode->_bf = 0;
}
else
{
subL->_bf = 0;
pNode->_bf = 0;
}

subLR->_bf = 0;
}

void _RotateRL(Node*& parent)
{
Node* pNode = parent;
Node* subRNode = parent->_right;
Node* subRLNode = subRNode->_left;
int bf = subRLNode->_bf;

_RotateR(parent->_right);
_RotateL(parent);

if (bf == 1)
{
subRNode->_bf = 0;
pNode->_bf = -1;
}
else if (bf == -1)
{
subRNode->_bf = 1;
pNode->_bf = 0;
}
else
{
subRNode->_bf = 0;
pNode->_bf = 0;
}

subRLNode->_bf = 0;
}
private:
Node* _root;
};

void test()
{
AVLTree<int ,int> t;
t.Insert(1, 1);
t.Insert(2, 1);
t.Insert(3, 1);
t.Insert(4, 1);
t.Insert(5, 1);
t.InOrder();
bool ret=t.IsBlance();
cout << ret << endl;
}

int main()
{
test();
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  AVL树 平衡二叉树