您的位置:首页 > 其它

AVL树(平衡二叉树)的构造

2016-10-27 19:27 567 查看
特点:平衡二叉树要求对于每一个节点来说,他的左右子树的高度之差不超过1,如果插入或者删除一个结点使得高度之差大于1,就要进行节点之间的旋转(左旋或者右旋),将二叉树重新维持在一个平衡状态

解决了二叉查找树退化成链表的问题,把插入,查找,删除时间复杂度最坏和最好情况都维持在O(logN)

旋转缺点:频繁旋转会牺牲掉O(logN)左右的时间,不过相对二叉查找树来说,时间上稳定了许多。

平衡二叉树的核心:

旋转算法



1:左左形式的不平衡

2.左右形式的不平衡

3.右左形式的不平衡

4.右右形式的不平衡

1,4一组

2,3一组

对于1:左旋 3的右子树给6的左边,6变成3的右子树,3成根

确定要换的根root和左子树left,left的右子树给root的左,root变成left的右

对于4:右旋 4的左子树给2的右边,2变成4的左子树,2成根

确定要换的根root和右子树right,right的左子树给root的右然后root变成right的左

对于2:先右旋左子树,再左旋根



对于3:先左旋右子书,再右旋根

代码如下:

#include <iostream>
#include <malloc.h>
#include <stack>

using namespace std;

typedef struct TreeNode
{
int height;
int data;
TreeNode* leftC;
TreeNode* rightC;
}TreeNode;

int getHeight(TreeNode* s)
{
if (s != NULL)
{
return s->height;
}
return -1;
}

void InitTree(TreeNode** list)
{
*list = (TreeNode*)malloc(sizeof(TreeNode));
(*list)->height = 0;
(*list)->leftC = NULL;
(*list)->rightC = NULL;
}

void leftRotate(TreeNode*& root)//左左
{
TreeNode *l1 = root;
TreeNode *l2 = root->leftC;
l1->leftC = l2->rightC;
l2->rightC = l1;
l1->height = (getHeight(l1->leftC) > getHeight(l1->rightC) ? getHeight(l1->leftC) : getHeight(l1->rightC)) + 1;
l2->height = (getHeight(l2->leftC) > getHeight(l2->rightC) ? getHeight(l2->leftC) : getHeight(l2->rightC)) + 1;
root = l2;
}

void rightRotate(TreeNode*& root)//右右
{
TreeNode *l1 = root;
TreeNode *l2 = root->rightC;
l1->rightC = l2->leftC;
l2->leftC = l1;
l1->height = getHeight(l1);
l2->height = getHeight(l2);
root = l2;
}

///左右,先右旋,再左旋
void DoubleRotateLR(TreeNode* &n1)
{
rightRotate(n1->leftC);
leftRotate(n1);
}

//右左,先左旋,后右旋
void DoubleRotateRL(TreeNode* &n1)
{
leftRotate(n1->rightC);
rightRotate(n1);
}

void Insert(TreeNode*& node, int data)
{
if (node == NULL)
{
TreeNode* tmp = (TreeNode*)malloc(sizeof(TreeNode));
tmp->data = data;
tmp->height = 0;
tmp->leftC = NULL;
tmp->rightC = NULL;
node = tmp;
return;
}
if (node->data > data)//结点的值大于data
{
Insert(node->leftC, data);//不断插入

if ((getHeight(node->leftC) - getHeight(node->rightC)) == 2)
{//说明需要左旋
if (data < node->leftC->data)
{
leftRotate(node);
}
else
{
DoubleRotateLR(node);
}
}
else if (node->data < data)//没有相同的值
{
Insert(node->rightC, data);
//如果高度之差为2的话就失去了平衡,需要旋转
if (2 == getHeight(node->rightC) - getHeight(node->leftC))
{
if (data > node->rightC->data)
{
rightRotate(node);
}
else
{
DoubleRotateRL(node);
}
}
}
}
node->height = (getHeight(node->leftC) > getHeight(node->rightC) ? getHeight(node->leftC) : getHeight(node->rightC)) + 1;
}

void preOrder(TreeNode* node)
{
if (node == NULL)
{
return;
}
cout << node->data << endl;
preOrder(node->leftC);
preOrder(node->rightC);
}

void  inOrderTraversal(TreeNode* root)//非递归中序遍历
{//先左,再中,最后右,对于每个子树也是一样的顺序
stack<TreeNode *> S;
while (true)
{
if (root)
{
S.push(root);
root = root->leftC;
}
else
{
if (S.empty())
{
break;
}
root = S.top();
cout << root->data << " ";
S.pop();
root = root->rightC;
}
}
}

void deleteNode(TreeNode* &node, int x)
{
if (node == NULL) return; //没有找到值是x的节点

if (x < node->data)
{
//如果x小于节点的值,就继续在节点的左子树中删除x
deleteNode(node->leftC, x);
if (2 == getHeight(node->rightC) - getHeight(node->leftC))
{
if (node->rightC->leftC && getHeight(node->rightC->leftC) > getHeight(node->rightC->rightC))
DoubleRotateRL(node);
else
rightRotate(node);
}
}
else if (x > node->data)
{
//如果x大于节点的值,就继续在节点的右子树中删除x
deleteNode(node->rightC, x);
if (2 == getHeight(node->leftC) > getHeight(node->rightC))
{
if (node->leftC ->rightC && getHeight(node->leftC->rightC) > getHeight(node->leftC->leftC))
DoubleRotateLR(node);
else
leftRotate(node);
}
}
else //如果相等,此节点就是要删除的节点
{
if (node->leftC && node->rightC) //此节点有两个儿子
{
TreeNode* ptr = node->rightC; //ptr指向节点的右儿子

while (ptr->leftC != NULL) ptr = ptr->leftC;//找到右子树中值最小的节点
//把右子树中最小节点的值赋值给本节点
node->data = ptr->data;
//删除右子树中最小值的节点
deleteNode(node->rightC, ptr->data);
if (2 == getHeight(node->leftC) - getHeight(node->rightC))
{
if (node->leftC->rightC && getHeight(node->leftC->rightC) > getHeight(node->leftC->leftC))
DoubleRotateLR(node);
else
leftRotate(node);
}
}
else
{
TreeNode* ptr = node;
//此节点有1个或0个儿子
if (node->leftC == NULL) //有右儿子或者没有儿子
node = node->rightC;
else if (node->rightC == NULL) //有左儿子
node = node->leftC;

delete ptr;
ptr = NULL;
}
}

if (node)
node->height = (getHeight(node->leftC) > getHeight(node->rightC) ? getHeight(node->leftC) : getHeight(node->rightC)) + 1;
}

int main()
{
TreeNode *head;
InitTree(&head);
for (int i = 5; i > 0; --i)
{
Insert((*head).leftC, i);
}
preOrder((*head).leftC);
inOrderTraversal((*head).leftC);
cout << endl;
deleteNode((*head).leftC, 1);
inOrderTraversal((*head).leftC);
cout << endl;
Insert((*head).leftC, 1);
deleteNode((*head).leftC, 4);
inOrderTraversal((*head).leftC);
cout << endl;
preOrder((*head).leftC);

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