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树的重点操作,也是难理解的地方
注:
高度:结点的高度是自下而上逐层累加的,我们以叶子结点的高度为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; }
相关文章推荐
- 平衡二叉树(AVL)的介绍及基本操作
- 平衡二叉树AVL的基本操作之插入
- 平衡二叉树AVL的基本操作之删除
- AVL--平衡二叉树的一些操作,杂记
- 平衡二叉树(AVL)各种操作详细分析
- 平衡二叉树AVL的一些基本概念(读书整理)
- 平衡二叉树AVL操作模板
- 数据结构----AVL平衡树----AVL平衡树的基本操作
- 平衡二叉树(AVL树)的基本操作(附有示意图)
- 平衡二叉树(AVL)的插入操作
- 1773 Problem A 算法9-9~9-12:平衡二叉树的基本操作
- 平衡二叉树的基本操作
- 平衡二叉树(AVL树)的基本操作
- 平衡二叉树(AVL)结点删除操作
- Geeks - AVL Tree Deletion 平衡二叉树 删除操作
- Dreamweaver学习之基本操作(文本、图片、链接)
- MySQL常用命令及基本操作总结
- 顺序表基本操作
- Ligerui表格基本操作(一)
- 基于循环链表的队列的基本操作