前一篇博客学习了高效动态表查找的二叉排序树,虽然在二叉排序树上实现的插入,删除和查找等基本操作的平均时间为O(log2(n)),但随着插入和删除操作导致树形的改变,成为单枝树,只能从根开始一层一个查找,实质变为顺序查找,此时就是最坏的情况,基本运算的时间会增至O(n);为了避免这种情况,我们可以使用平衡二叉树,使之即保存BST性质又保证树的高度至多左右子树相差一。平衡二叉树有较多种,我们主要介绍较为著名的AVL树。
平衡二叉树(AVL)
1.概念介绍
平衡二叉树(Balanced Binary Tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
我们通过平衡因子来具体实现上述的平衡二叉树的定义,平衡因子的定义为:平衡二叉树中每一个结点有一个平衡因子域,每个结点的平衡因子是该结点左子树的高度减去右子树的高度。若一棵二叉树中所有结点的平衡因子的绝对值小于或等于1,则该树成为平衡二叉树。
例如:
每个结点旁边标记的就是该结点的平衡因子,具体计算如下:
我们看图a,左子树高度减去右子树高度,得
5的结点平衡因子就是 3 - 2 = 1;
2的结点平衡因子就是 1 - 2 = -1;
4的结点平衡因子就是 1 - 0 = 1;
6的结点平衡因子就是 0 - 1 = -1;
2.结点插入
首先我们定义树结点的结构为:
//树结点结构 struct node { int data;//数据 int bf;//平衡因子 node*lchild,*rchild; node() { lchild=rchild=NULL; } };
在平衡二叉树中插入结点与二叉查找树最大的不同在于要随时保证插入后整棵二叉树是平衡的。若插入的新结点破坏了平衡性首先要从根节点到该新结点的路径逆向找到第一个失去平衡的结点。在这里我们要介绍失去平衡的最小子树的概念。
失去平衡的最小子树是指以离插入结点最近,且平衡因子绝对值大于1的结点作为根的子树。假设用A表示失去平衡的最小子树的根结点,则调整该子树的操作可归纳为下列四种情况。(1)LL型调整
由于在A的左孩子B的左子树上插入结点F,使A的平衡因子由1增至2而失去平衡。故需进行一次顺时针旋转操作。 即将A的左孩子B向右上旋转代替A作为根结点,A向右下旋转成为B的右子树的根结点。而原来B的右子树则变成A的左子树。
如图所示:
代码实现:
void L_rotata(node * &p){//左旋, node * rc=p->rchild; p->rchild=rc->lchild; rc->lchild=p; p=rc; }
(2)RR型调整
由于在A的右孩子C 的右子树上插入结点F,使A的平衡因子由-1减至-2而失去平衡。故需进行一次逆时针旋转操作。即将A的右孩子C向左上旋转代替A作为根结点,A向左下旋转成为C的左子树的根结点。而原来C的左子树则变成A的右子树。
如图所示:
实现代码:
void R_rotate(node * &p){//右旋, node * lc=p->lchild; p->lchild=lc->rchild; lc->rchild=p; p=lc; }
(3)LR型调整
由于在A的左孩子B的右子数上插入结点F,使A的平衡因子由1增至2而失去平衡。故需进行两次旋转操作(先逆时针,后顺时针)。即先将A结点的左孩子B的右子树的根结点D向左上旋转提升到B结点的位置,然后再把该D结点向右上旋转提升到A结点的位置。即先使之成为LL型,再按LL型处理
如图所示:
先将圆圈部分先调整为平衡树,然后将其以根结点接到A的左子树上,此时成为LL型,再按LL型处理成平衡型。
实现代码:
void Leftbalance(node * &T){//左子树的平衡处理 node * lc=T->lchild; switch(lc->bf){ //LL的情况 case LH: T->bf=lc->bf=EH; R_rotate(T); break; case RH://LR的情况,同时针对rd上的不同情况,进行对T,lc的平衡因子的设置 node * rd=lc->rchild; switch(rd->bf){ case LH:T->bf=RH; lc->bf=EH;break; case EH:T->bf=lc->bf=EH;break; case RH:T->bf=EH;lc->bf=LH;break; } rd->bf=EH; L_rotata(T->lchild); R_rotate(T); } }
(4)RL型调整
由于在A的右孩子C的左子树上插入结点F,使A的平衡因子由-1减至-2而失去平衡。故需进行两次旋转操作(先顺时针,后逆时针),即先将A结点的右孩子C的左子树的根结点D向右上旋转提升到C结点的位置,然后再把该D结点向左上旋转提升到A结点的位置。即先使之成为RR型,再按RR型处理。
如图所示:
先将圆圈部分先调整为平衡树,然后将其以根结点接到A的左子树上,此时成为RR型,再按RR型处理成平衡型。
实现代码:
void Rightbalance(node * &T)//右子树的平衡处理,与左子树的平衡处理类似 { node * rc=T->rchild; switch (rc->bf) { case RH: T->bf=rc->bf=EH; L_rotata(T);break; case LH: node * ld=rc->lchild; switch(ld->bf){ case LH: T->bf=EH; rc->bf=RH;break; case EH: T->bf=rc->bf=EH;break; case RH: T->bf=LH; rc->bf=EH;break; } ld->bf=EH; R_rotate(T->rchild); L_rotata(T); } }
含有n个结点的平衡二叉树的平均查找长度为O(log2(n));
附上源码地址:https://github.com/longpo/algorithm/tree/master/AVL
相关推荐
算法-理论基础- 查找- 平衡二叉树(包含源程序).rar
二叉树查找算法
平衡二叉查找树代码 AVL 二叉树 查找树
树 * 字典树 * 遍历-层次遍历 * 遍历-中序遍历-非递归 ...* 二叉查找树-从有序链表构造平衡的二叉查找树 * 二叉树-的最大深度 数组&字符串 查找排序 排列组合 动态规划 树 链表 数学 位运算 编程之美
二叉平衡树:若不是空树,则(1)左右子树都是平衡二叉树;(2)左右子树的深度之差的绝对值不超过1。 本次实验是利用二叉排序树和平衡二叉树达到以下目的:(1)以回车('\n')为输入结束标志,输入数列L,生成一棵二叉...
主要介绍了查找算法,包括顺序查找、折半查找、分块查找和树形查找。后面会继续更新树形查找的相关内容,包括红黑树、B树、B+树、散列表等。除了讲一下他的算法思想,也会对他做一定的性能分析
二叉排序、查找树: 1、用随机函数生成10个待排序元素; 2、利用二叉查找树输出升序序列; 3、利用同一棵二叉查找树输出降序序列; 4、写出查找的递归函数;注意:递归出口的处理要求:二叉排序树的程序填空:修改 ...
两种查找算法,二叉树查找,折半查找 时通过严蔚敏那本书的算法而来
二叉树查找的算法和演示过程二叉树查找的算法和演示过程二叉树查找的算法和演示过程二叉树查找的算法和演示过程二叉树查找的算法和演示过程
09-003二分查找的平均查找长度、查找树表 09-004动态查找表:二叉排序树的插入和删除操作 09-005查找的性能分析、平衡二叉树、B-树的定义 09-006B-树的查找过程、B+树的定义与查找 09-007键树的结构特点、哈希表的...
C语言编写的 数据结构 平衡二叉树 演示、含课程设计报告 多种输出平衡二叉树格式
cout****** 二叉树二叉链表结构测试程序 ******"; cout* 0--退出 *"; cout* 1--交互创建二叉树 *"; cout* 2--文件创建二叉树 *"; cout* 3--完全二叉树序列创建二叉树 *"; cout* 4--打印二叉树 *"; cout* 5--...
单链表的基本操作,二叉树的遍历,折半查找和二叉排序树,内部排序等共四个实验的实现过程。
用函数实现如下平衡二叉排序树算法: (1) 插入新结点 (2) 前序、中序、后序遍历二叉树 (递归) (3) 前序、中序、后序遍历的非递归算法 (4) 层次遍历二叉树 (5) 在二叉树中查找给定关键字(函数返回值...
实现动态查找表的三种基本功能:查找、插入和删除 (1)初始,平衡二叉树为空树,操作界面给出查找、插入和删除三种操作供选择。每种操作均要提示输入关键字。每次插入或删除一个结点后,应更新平衡二叉树的显示。...
图+查找+排序+循环链表+循环链表+数组+广义表+二叉树与树的转换+哈夫曼树
(2) 平衡二叉树的显示可采用如6.3题要求的凹入表形式,也可以采用图形界面画出树形。 (3) 教科书已给出查找和插入算法,本题重点在于对删除算法的设计和实现。假设要删除关键字为x的结点。如果x不在叶子结点上,则用...
基于二叉链表的二叉树,实现了二叉树的多种操作:添加、删除、拷贝、清空、树深度计算、父节点、兄弟节点获取、先中后序递归及非遍历、按层次遍历、中序迭代器(非递归算法)、节点查找、先序和中序序列重建二叉树、...
(2)平衡二叉树的显示可采用如6.69题要求的凹入表形式,也可以采用图形界面画出树形。 (3)教科书已给出查找和插入算法,本题重点在于对删除算法的设计和实现。假设要删除关键字为x的结点。如果x不在叶子结点...
基于左右旋平衡二叉树以及相关树的算法c源码+使用说明.zip 二叉(平衡)查找树 一个可以自动生成图像的二叉查找树 ## Getting Started *bst* requires: * gcc * make * graphviz you can build *bst* from ...