读书人

数据结构查寻(2)-平衡的二叉查找树(AV

发布时间: 2012-12-27 10:17:10 作者: rapoo

数据结构查找(2)--平衡的二叉查找树(AVL树)
上篇博客介绍了二叉查找树,来看下各项操作的时间复杂度。

查找 插入 删除o(log n ) o(1) o(1)有序 链表 链表

我们可以想象下,在构造二叉查找树的时候,如果按以下递增序列构造如:2 4 5 6 7 8,那么构造出来的查找二叉树将会是接近链表的形式,这样就增加了查找的时间复杂度。
也就是说,这课树失去了平衡。我们看看下面这个图就明白了。
数据结构查寻(2)-平衡的二叉查找树(AVL树)
这样一来,b虽然也是一颗二叉查找树,但是查找效率大大下降。所以,我们引入了平衡的二叉查找树(AVL)树。

1.平衡
关键是“平衡”这个概念的理解。
定义如下:
树中每个结点的左、右子树深度之差的绝对值不大于1

节点的平衡因子是它的左子树的高度减去它的右子树的高度(有时相反)。带有平衡因子1、0或 -1的节点被认为是平衡的。带有平衡因子 -2或2的节点被认为是不平衡的,并需要重新平衡这个树。平衡因子可以直接存储在每个节点中,或从可能存储在节点中的子树高度计算出来。
下面给个例子,我们以左子树的高度减去它的右子树的高度作为平衡因子。
数据结构查寻(2)-平衡的二叉查找树(AVL树)

2.旋转
平衡树的关键,就是如何达到平衡,这里的关键技术就是旋转了。

下面引出的是基本概念:

有四种种情况可能导致二叉查找树不平衡,分别为:

(1)LL:插入一个新节点到根节点的左子树(Left)的左子树(Left),导致根节点的平衡因子由1变为2

(2)RR:插入一个新节点到根节点的右子树(Right)的右子树(Right),导致根节点的平衡因子由-1变为-2

(3)LR:插入一个新节点到根节点的左子树(Left)的右子树(Right),导致根节点的平衡因子由1变为2

(4)RL:插入一个新节点到根节点的右子树(Right)的左子树(Left),导致根节点的平衡因子由-1变为-2

针对四种种情况可能导致的不平衡,可以通过旋转使之变平衡。有两种基本的旋转:

(1)左旋转:将根节点旋转到(根节点的)右孩子的左孩子位置

(2)右旋转:将根节点旋转到(根节点的)左孩子的右孩子位置
给大家看张wiki上面的图,一目了然:

数据结构查寻(2)-平衡的二叉查找树(AVL树)

2.1 左左(LL)情况
针对左左这种情况,我们需要右旋。看上面的图就应该很明白。
我看人家的代码,这种情况的函数名叫做RightRotate,后来自己写着写着因为函数名把自己给搞晕了。所以我的函数是这样命名的:
左左情况,函数名就叫LeftLeft,这样就不用引入什么左旋右旋这样的概念了。免得把自己搞乱。如果大家不喜欢的话可以按照自己的理解来~~
我们附上代码:

AVLTree.cpp
#include "AVLTree.h"//functionsvoid Chose();void Insert();void Output(AVLTree T);void PrintTree(AVLTree T);void Delete();int main(){while (1){Chose();switch(chos){case 'i':Insert();break;case 'd':Delete();break;case 'e':exit(0);}}return 0;}void Chose(){printf("i) Insert a point \n"   "d) Delete a point \n"   "e) exit  \n"   "Input your choise \n");scanf("%c", &chos);getchar();}void Insert(){printf("\nInput the point you want to Insert: ");scanf("%d", &input);getchar();T = AVLInsert(T);Output(T);}void Output(AVLTree T){if (T == NULL)printf("None\n");else{printf("%d\troot\n", T->data);PrintTree(T);}}//Tree printvoid PrintTree(AVLTree T){if (T->lchild){printf("Lchild\t%d\t[parent:%d]\n", T->lchild->data, T->data);PrintTree(T->lchild);}if (T->rchild){printf("Rchild\t%d\t[parent:%d]\n", T->rchild->data, T->data);PrintTree(T->rchild);}}void Delete(){}



文献参考:

图片参考:
http://zh.wikipedia.org/wiki/AVL%E6%A0%91
基本概念参考:
http://dongxicheng.org/structure/avl/
代码参考:
http://www.asiteof.me/2010/06/avl/

读书人网 >编程

热点推荐