您的位置:首页 > 其它

AVL---平衡二叉树的基本操作

2017-07-20 21:07 309 查看
AVL--平衡二叉树,是二叉树中的一个很重要的树类,它是BST--二叉排序树的变种,二叉排序树在这里就不再赘述,AVL在BST的基础上面增加一个功能,那就是一个结点的左右子树的高度之差的绝对值不能超过1,也就是说一个结点的左右子树差值只能是“1,0,-1”这三个数。
注:
高度:结点的高度是自下而上逐层累加的,我们以叶子结点的高度为1,一个有7个结点的满二叉树的根节点的高度为3。

下面我们就来以代码的形式对AVL树的一些基本操作进行了解:
//平衡二叉树的数据结构
typedef int DataType;//定义数据类型的别名,方便改动,此处以int为例

struct AVLTreeNode
{
DataTypedata;//结点的数据值
int hight;//结点的高度
AVLTreeNode* LChild;//结点左孩子
AVLTreeNode* RChild;//结点有孩子
};

//平衡二叉树的创建
AVLTreeNode* AvltreeCreateNode(Type key, AVLTreeNode* left, AVLTreeNode* right)
{
AVLTreeNode* pNode = NULL;

if ((pNode = (AVLTreeNode*)malloc(sizeof(AVLTreeNode))) == NULL)//判断结点是否malloc成功
{
return NULL;
}

pNode->key = key;
pNode->LChild = left;//此处只有左右结点不为叶子结点时才会有实际作用,在中间创建结点,
pNode->RChild = right;//将其他邻接结点作为左右子树传入并赋值

return pNode;
}

//获得高度
int GetAvlHight(AVLTreeNode*pNode)//获得当前结点的高度
{
return pNode->hight;
}

//求最大值
int Max(int a, int b)//当求结点高度时,求其左右子树高度的二者中的最大值,然后加一
{
return a > b ? a : b;
}

//递归查找平衡二叉树中值为data的结点
AVLTreeNode* AvlSearchRecurison(AVLTreeNode* pNode, Type data)
{
if (pNode == NULL || pNode->key == data)//如果结点为空时,有两种情况,一个树为空,另一个树中没有具有data值的结点
{
return pNode;
}
if (data< pNode->data)//当data值小于结点的data值,那么进入左子树进行递归,否则进入右子树进行递归
{
return AvlSearchRecurison(pNode->LChild, data);
}
else
{
return AvlSearchRecurison(pNode->RChild, data);
}
}

//非递归查找平衡二叉树值为data的结点
AVLTreeNode* AvlSearch(AVLTreeNode* pNode, Type data)
{
while (pNode != NULL || pNode->data != data)
{
if (data <pNode->data)
{
pNode = pNode->LChild;
}
else
{
pNode = pNode->RChild;
}
}

return pNode;
}

//查找树中最小结点
AVLTreeNode* SearchAvlTreeMinimunNode(AVLTreeNode* pNode)
{
while (pNode->LChild != NULL)//AVL树继承了BST树的性质,左子树 < 根节点 < 右子树,所以查找最小值进入左子书查找
{
pNode = pNode->LChild;
}

return pNode;
}

//查找树中最大结点
AVLTreeNode* SearchAvlTreeMaximunNode(AVLTreeNode* pNode)
{
while (pNode->RChild != NULL)//AVL树继承了BST树的性质,左子树 < 根节点 < 右子书,所以查找最大值进入右子书查找
{
pNode = pNode->RChild;
}

return pNode;
}

注:下面是AVL树的重点操作,也是难理解的地方



//LL旋转
AVLTreeNode* LeftLeftRotation(AVLTreeNode* pTop)
{
AVLTreeNode* pLeft;

pLeft = pTop->LChild;
pTop->LChild = pLeft->RChild;
pLeft->RChild = pTop;

pTop->hight = Max(GetAvlHight(pTop->LChild), GetAvlHight(pTop->RChild)) + 1;
pLeft->hight = Max(GetAvlHight(pLeft->LChild), pTop->hight) + 1;

return pLeft;
}

//RR旋转
AVLTreeNode* RightRightRotation(AVLTreeNode* pTop)//RR旋转
{
AVLTreeNode* pRight;

pRight = pTop->RChild;
pTop->RChild = pRight->LChild;
pRight->LChild = pTop;

pTop->hight = Max(GetAvlHight(pTop->LChild), GetAvlHight(pTop->RChild)) + 1;
pRight->hight = Max(pTop->hight, GetAvlHight(pRight->RChild)) + 1;

return pRight;
}

//LR旋转
AVLTreeNode* LeftRightRotation(AVLTreeNode* pTop)
{
pTop->LChild = RightRightRotation(pTop->LChild);

return LeftLeftRotation(pTop);
}

//RL旋转
AVLTreeNode* RightLeftRotation(AVLTreeNode* pTop)
{
pTop->RChild = LeftLeftRotation(pTop->RChild);

return RightRightRotation(pTop);
}

//平衡二叉树插入
AVLTreeNode* AvlTreeInsert(AVLTreeNode* pNode, Type data)
{
if (pNode == NULL)
{
pNode = AvltreeCreateNode(data, NULL, NULL);
if (pN
8b3d
ode == NULL)
{
throw std::exception("Create avltree node failed!");
}
}
else if (data< pNode->data)
{
pNode->LChild = AvlTreeInsert(pNode->LChild, data);

if (GetAvlHight(pNode->LChild) - GetAvlHight(pNode->RChild) == 2)
{
if (data< pNode->LChild->data)
{
pNode = LeftLeftRotation(pNode);
}
else
{
pNode = LeftRightRotation(pNode);
}
}
}
else if (data>pNode->data)
{
pNode->RChild = AvlTreeInsert(pNode->RChild, data);

if (GetAvlHight(pNode->RChild) - GetAvlHight(pNode->LChild) == 2)
{
if (data> pNode->RChild->data)
{
pNode = RightRightRotation(pNode);
}
else
{
pNode = RightLeftRotation(pNode);
}
}
}
else
{
throw std::exception("插入失败,不允许添加相同的结点");
}

pNode->hight = Max(GetAvlHight(pNode->LChild), GetAvlHight(pNode->RChild)) + 1;

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