重学数据结构008——AVL树
来源:互联网 发布:Vb大漠插件注册 编辑:程序博客网 时间:2024/04/25 10:21
之前学习了二叉查找树的及相关操作。二叉查找树的大部分主要操作的复杂度都是O(logN)量级的。现在考虑这样一种情况:通过集合{3,2,4,1,0,-1,-2,-3,-4,-4}中的元素来构建二叉查找树,得到的树如图所示:
如果现在我们需要查找元素-4,那么时间复杂度还是是O(logN)吗?有个更加极端的例子,假设数据集是{6,5,3,1,0,-1,-2,-3,-4,-4}呢?再去查找元素-4,其复杂度已经是O(N)了。也就是说,二叉查找树的查找优势完全不复存在了。在这样的情况下,以前的牛人们又想出了别的办法:让二叉查找树除了满足现有条件外,添加平衡条件,形成平衡二叉树。AVL树是其中一种典型的平衡二叉树,
AVL树是带有平衡条件的二叉查找树。在满足所有二叉查找树条件下,还加入了平衡条件:AVl树的每个节点的左右子树的高度差必须<=1。 在我使用的这本教材中,定义空树的高度为-1,一个节点的树的高度定义为0。
为了满足平衡条件,AVL树的基本操作一般涉及运作同在不平衡的二叉查找树所运作的同样的算法。但是要进行预先或随后做一次或多次所谓的"AVL旋转"。
涉及到的几种情况如下图所示:
AVL树的基本操作代码如下:
#include <stdio.h>#include <stdlib.h>#define MAX(X,Y) ((X > Y) ? X : Y)typedef int ElementType;typedef struct AvlNode *Position;typedef struct AvlNode *AvlTree;/************************************************************************//* Avl树的数据结构定义以及节本操作定义 *//************************************************************************/struct AvlNode {ElementType Element;int Height;AvlTree Left,Right;};AvlTree MakeEmpty(AvlTree T); /*清空Avl树*/Position Find(ElementType X, AvlTree T); /*在Avl树中查找指定的元素*/Position FindMax(AvlTree T); /*在Avl树中查找最大元素*/Position FindMin(AvlTree T); /*在Avl树中查找最小元素*/AvlTree Insert(ElementType X, AvlTree T); /*在Avl树中插入指定元素*/AvlTree Delete(ElementType X, AvlTree T); /*在Avl树中删除指定元素*/ElementType Retrieve(Position P); /*获取指定节点的元素值*/int Height(Position P); /*获得指定节点的高度值*/Position SingleRotateWithLeft(Position P); /*单右旋转*/Position SingleRotateWithRight(Position P); /*单左旋转*/Position DoubleRotateWithLeft(Position P);/*双左右旋转*/Position DoubleRotateWithRight(Position P);/*双右左旋转*/int main(void) {return 0;}/************************************************************************//* 清空AVL树的操作与清空普通二叉树相同 *//************************************************************************/AvlTree MakeEmpty(AvlTree T) {if (!T){MakeEmpty(T->Left);MakeEmpty(T->Right);free(T);}return NULL;}/************************************************************************//*在Avl树中查找指定的元素,与二叉查找树的操作相同 *//************************************************************************/Position Find(ElementType X, AvlTree T){if (T == NULL){return NULL;} else{if (X < T->Element){return Find(X,T->Left);}else if(X > T->Element){return Find(X, T->Right);}else{return T;}}}/************************************************************************//* 在Avl树中查找最大值(递归写法) *//************************************************************************/Position FindMax(AvlTree T){if (T == NULL){return NULL;} else{if (T->Right == NULL){return NULL;} else{return FindMax(T->Right);}}}/************************************************************************//* 在Avl树中查找最小值(非递归写法) *//************************************************************************/Position FindMin(AvlTree T){if (T == NULL){return NULL;}else{while (T->Left != NULL){T = T->Left;}return T;}}/************************************************************************//* 返回指定节点的高度信息 *//************************************************************************/int Height(Position P) {if (P == NULL){return -1;}else{return P->Height;}}/************************************************************************//* 单旋转:右旋转 *//* 使用条件:这个函数只适合当P有左子树时调用; *//* 作用:在P和其左子树根节点之间执行一次单右旋转*//************************************************************************/Position SingleRotateWithLeft(Position P){Position LChild = P->Left;P->Left = LChild->Right; /*将P的左孩子设置成LChild的右孩子*/LChild->Right = P;P->Height = MAX(Height(P->Left),Height(P->Right)) + 1;/*更新高度信息*/LChild->Height = MAX(Height(LChild->Left),P->Height) + 1;return LChild;/*新的根节点*/}/************************************************************************//* 单旋转:左旋转 *//* 使用条件:这个函数只适合当P有右子树时调用;*//* 作用:在P和其右子树根节点之间执行一次单左旋转*//************************************************************************/Position SingleRotateWithRight(Position P){Position RChild = P->Right; /*将P的右孩子设置成RChild的右孩子*/P->Right = RChild->Left;RChild->Left = P;P->Height = MAX(Height(P->Left),Height(P->Right)) + 1;/*更新高度信息*/RChild->Height = MAX(Height(RChild->Right),P->Height) + 1;return RChild;/*新的根节点*/}/************************************************************************//* 双旋转:左右旋转 *//* 使用条件:适合于当P有左孩子,而左孩子有右孩子 *//* 作用:*//************************************************************************/Position DoubleRotateWithLeft(Position P){P->Left = SingleRotateWithRight(P->Left); /*先进行左旋转*/return SingleRotateWithLeft(P); /*再进行又旋转*/}/************************************************************************//* 双旋转:右左旋转 *//* 使用条件:适合于当P有右孩子,而右孩子有左孩子 *//* 作用:*//************************************************************************/Position DoubleRotateWithRight(Position P){P->Right = SingleRotateWithLeft(P->Right); /*先进行右旋转*/return SingleRotateWithRight(P); /*再进行左旋转*/}/************************************************************************//* AVL树插入操作 *//************************************************************************/AvlTree Insert(ElementType X, AvlTree T){/*如果T是一棵空树,那么创建一个节点作为树的根节点*/if (T == NULL){T = malloc(sizeof(struct AvlNode));if(T == NULL){fprintf(stderr,"Out of space!");}else{T->Element = X;T->Left = NULL;T->Right = NULL;T->Height = 0;}}else{if (X < T->Element){T->Left = Insert(X,T->Left);/*判断是否打破了破了平衡条件*/if (Height(T->Left) - Height(T->Right) == 2){/*判断是四种情况中的哪一种情况*/if (X < T->Left->Element){T = SingleRotateWithLeft(T);}else if (X > T->Left->Element){T = DoubleRotateWithLeft(T);}}}else if (X > T->Element){T->Right = Insert(X,T->Right);if (Height(T->Right) - Height(T->Left) == 2){if(X < T->Right->Element){T = DoubleRotateWithRight(T);}else if (X > T->Right->Element){T = SingleRotateWithRight(T);}}}else{/*元素已经存在于AVL树中,因此不需要再做别的工作*/}/*更新数的高度信息*/T->Height = MAX(Height(T->Left),Height(T->Right)) + 1;}return T;}
上述AVL旋转的示意图来自维基百科:AVL树
- 重学数据结构008——AVL树
- 数据结构—AVL树
- 数据结构——AVL树
- 重学数据结构007——二叉查找树
- 重学数据结构系列之——二叉树基础
- 数据结构——AVL树的插入
- 数据结构 — AVL树(平衡二叉树)
- 重学数据结构002——桶排序、基数排序
- 重学数据结构系列之——线性表基础
- 重学数据结构系列之——队列
- 重学数据结构系列之——栈
- 重学数据结构系列之——哈希表
- 重学数据结构系列之——二叉排序树
- 重学数据结构系列之——图的储存
- 重学数据结构系列之——八大排序算法
- 重学数据结构系列之——总结
- 【数据结构】平衡二叉树[AVL树](一)——插入
- 【数据结构】平衡二叉树[AVL树](二)——删除
- 使用APIHOOK实现进程隐藏
- 关于 for update
- 说说字符集和编码
- GDAL库的编译
- 通俗语言讲解PON
- 重学数据结构008——AVL树
- 深入了解字符集和编码
- Chip in mario(JAVA GAME)
- android不让弹出键盘挡住View
- 关于 for update
- Binder机制分析(2)——从MediaService中看Binder的实现和使用(1)
- JQUERY获取text,areatext,radio,checkbox,select值
- 看到两个写的很好的关于字符集,编码的文章,推荐大家看看
- Binder机制分析(2)——从MediaService中看Binder的实现和使用(2)