avl树例题
- 格式:ppt
- 大小:78.50 KB
- 文档页数:5
AVL树的平衡算法(JAVA实现)1、概念: AVL树本质上还是⼀个⼆叉搜索树,不过⽐⼆叉搜索树多了⼀个平衡条件:每个节点的左右⼦树的⾼度差不⼤于1。
⼆叉树的应⽤是为了弥补链表的查询效率问题,但是极端情况下,⼆叉搜索树会⽆限接近于链表,这种时候就⽆法体现⼆叉搜索树在查询时的⾼效率,⽽最初出现的解决⽅式就是AVL树。
如下图:2、旋转 说到AVL树就不得不提到树的旋转,旋转是AVL维持平衡的⽅式,主要有以下四种类型。
2.1、左左旋转 如图2-1所⽰,此时A节点的左树与右树的⾼度差为2,不符合AVL的定义,此时以B节点为轴⼼,AB间连线为转轴,将A节点旋转⾄B节点下⽅,由B节点的⽗节点变成⼦节点。
实现所有节点的左右⼦树⾼ 度差⼩于等于1。
如图2-2。
2.2、右右旋转 右右旋转与左左旋转类似,但是动作相反,如图2-3,2-4所⽰,以B节点为轴⼼,BC间连线为轴,将C节点旋转⾄B下⽅,成为B的⼦节点。
实现所有节点的左右⼦树⾼度差⼩于等于1。
2.3、左右旋转 左右旋转稍复杂⼀点,需要旋转两次,如果⽤左左旋转的⽅式直接旋转图2-5中的树,会变成图2-8的样⼦,此时B节点的左右⼦树⾼度差依然没有平衡,所以要先对2-5的树做⼀步处理,就是以BC为轴, 将C节点旋转⾄B节点的位置,如图2-6所⽰,此时就将树转换成了左左旋转的场景,之后使⽤左左旋转即可完成平衡。
2.4、右左旋转 右左旋转与左右旋转类似,也是旋转两次。
如下图,具体细节请看下⾯的代码详解。
3、代码实现 3.1、新增 ⼆叉树的插⼊不在赘述,这⾥只分析插⼊时的平衡⽅法。
如果新增节点没有兄弟节点时会引起树的⾼度变化,此时需要对上层节点的平衡值进⾏修改,如果出现了不平衡树,则需要调⽤平衡⽅法,代码如下:private void balance(Node node){Node parent = node.getParent();Node node_middle = node;Node node_prev = node;Boolean avl = true;do{if(node_middle == parent.getLeft() && (-1 <= parent.getAVL()-1 && parent.getAVL()-1 <= 1)){//node_middle为parent的左树,此时parent左树⾼度+1不会造成不平衡。
数据结构试题一、单选题1、在数据结构的讨论中把数据结构从逻辑上分为(C )A 内部结构与外部结构B 静态结构与动态结构C 线性结构与非线性结构D 紧凑结构与非紧凑结构。
2、采用线性链表表示一个向量时,要求占用的存储空间地址(D )A 必须是连续的B 部分地址必须是连续的C 一定是不连续的D 可连续可不连续3、采用顺序搜索方法查找长度为n的顺序表时,搜索成功的平均搜索长度为( D )。
A nB n/2C (n-1)/2D (n+1)/24、在一个单链表中,若q结点是p结点的前驱结点,若在q与p之间插入结点s,则执行( D )。
A s→link = p→link; p→link = s;B p→link = s; s→link = q;C p→link = s→link; s→link = p;D q→link = s; s→link = p;5、如果想在4092个数据中只需要选择其中最小的5个,采用( C )方法最好。
A 起泡排序B 堆排序C 锦标赛排序D 快速排序6、设有两个串t和p,求p在t中首次出现的位置的运算叫做( B )。
A 求子串B 模式匹配C 串替换D 串连接7、在数组A中,每一个数组元素A[i][j]占用3个存储字,行下标i从1到8,列下标j从1到10。
所有数组元素相继存放于一个连续的存储空间中,则存放该数组至少需要的存储字数是( C )。
A 80B 100C 240D 2708、将一个递归算法改为对应的非递归算法时,通常需要使用( A )。
A 栈B 队列C 循环队列D 优先队列9、一个队列的进队列顺序是1, 2, 3, 4,则出队列顺序为( C )。
10、在循环队列中用数组A[0..m-1] 存放队列元素,其队头和队尾指针分别为front和rear,则当前队列中的元素个数是( D )。
A ( front - rear + 1) % mB ( rear - front + 1) % mC ( front - rear + m) % mD ( rear - front + m) % m11、一个数组元素a[i]与( A )的表示等价。
纸上谈兵:AVL树⼆叉搜索树的深度与搜索效率我们在中提到,⼀个有n个节点的⼆叉树,它的最⼩深度为log(n),最⼤深度为n。
⽐如下⾯两个⼆叉树:深度为n的⼆叉树深度为log(n)的⼆叉树这两个⼆叉树同时也是⼆叉搜索树(参考)。
注意,log以2为基底。
log(n)是指深度的量级。
根据我们对深度的定义,精确的最⼩深度为floor(log(n)+1)。
我们将处于同⼀深度的节点归为⼀层。
如果除最后⼀层外的其他层都被节点填满时,⼆叉树有最⼩深度log(n)。
⼆叉搜索树的深度越⼩,那么搜索所需要的运算时间越⼩。
⼀个深度为log(n)的⼆叉搜索树,搜索算法的时间复杂度也是log(n)。
然⽽,我们在中已经实现的插⼊和删除操作并不能让保持log(n)的深度。
如果我们按照8,7,6,5,4,3,2,1的顺序插⼊节点,那么就是⼀个深度为n的⼆叉树。
那么,搜索算法的时间复杂度为n。
n和log(n)的时间复杂度意味着什么呢?时间复杂度代表了完成算法所需要的运算次数。
时间复杂度越⼩,算法的速度越快。
可以看到,随着元素的增加,log(n)的时间复杂度的增长要远⼩于n。
所以,我们⾃然希望⼆叉搜索树能尽可能保持log(n)的深度。
在上⾯深度为n的例⼦中,我们发现,每个节点只有左节点被填满。
树的每⼀层都有很多空位。
能不能尽可能减少每⼀层的空位呢? (相应的,减少树的深度)“紧致”的树⼀种想法是先填满⼀层,再去填充下⼀层,这样就是⼀个完全⼆叉树(complete binary tree)。
这样的⼆叉树实现插⼊算法会⽐较复杂。
我们将介绍⼀种思路相似,但⽐较容易实现的树状数据结构——AVL树。
AVL树AVL树是根据它的发明者G. M. A delson-V elskii和E. M. L andis命名的。
它是⼀种特殊的⼆叉搜索树。
AVL树要求: 任⼀节点的左⼦树深度和右⼦树深度相差不超过1(空树的深度为0。
注意,有的教材中,采⽤了不同的深度定义⽅法,所以空树的深度为-1)下⾯是AVL树:AVL树的特性让⼆叉搜索树的节点实现平衡(balance):节点相对均匀分布,⽽不是偏向某⼀侧。
数据结构与算法模拟习题(附参考答案)一、单选题(共86题,每题1分,共86分)1.具有5个顶点的有向完全图有多少条弧?A、16B、20C、25D、10正确答案:B2.下列程序的时间复杂度为()。
i = 0; s = 0;while(s < n){i++;s = s + i;}A、Θ(n)B、Θ(1)C、Θ(n2)D、Θ(n½)正确答案:D3.栈和队列的共同点是()。
A、没有共同点B、只允许在端点处插入和删除元素C、都是先进后出D、都是先进先出正确答案:B4.下面描述中正确的为( )。
A、线性表的逻辑顺序与物理顺序总是一致的B、线性表的顺序存储表示优于链式存储表示。
C、线性表若采用链式存储表示时所有结点之间的存储单元地址可连续可不连续。
D、二维数组是其数组元素为线性表的线性表。
正确答案:C5.对N个不同的数据采用冒泡算法进行从大到小的排序,下面哪种情况下肯定交换元素次数最多?A、从大到小排好的B、元素无序C、元素基本有序D、从小到大排好的正确答案:D6.表达式3*2^(4+2*2-6*3)-5求值过程中当扫描到6时,对象栈和算符栈为(),其中^为乘幂。
A、3, 2, 8;( * ^ -B、3, 2, 4, 2, 2;( * ^ ( -C、3, 2, 4, 1, 1;( ^ ( + -D、3, 2, 8;( * ^ ( -正确答案:D7.二叉树的高度若根节点为高度1,一棵具有 1025 个结点的二叉树的高度为▁▁▁▁▁ 。
A、10~1024 之间B、11~1025 之间C、10D、11正确答案:B8.数据采用链式存储结构时,要求( )A、每个节点占用一片连续的存储区域B、所有节点占用一片连续的存储区域C、节点的最后一个数据域一定是指针类型D、每个节点有多少个后继就设多少个指针域正确答案:A9.在N个结点的顺序表中,算法的时间复杂度为O(1)的操作是:A、将N个结点从小到大排序B、删除第i个结点(1≤i≤N)C、访问第i个结点(1≤i≤N)和求第i个结点的直接前驱(2≤i≤N)D、在第i个结点后插入一个新结点(1≤i≤N)正确答案:C10.将元素序列{18, 23, 4, 26, 31, 33, 17, 39}按顺序插入一个初始为空的、大小为13的散列表中。
AVL树1,AVL树⼜称平衡⼆叉树,它⾸先是⼀颗⼆叉查找树,但在⼆叉查找树中,某个结点的左右⼦树⾼度之差的绝对值可能会超过1,称之为不平衡。
⽽在平衡⼆叉树中,任何结点的左右⼦树⾼度之差的绝对值会⼩于等于 1。
2,为什么需要AVL树呢?在⼆叉查找树中最坏情况下查找某个元素的时间复杂度为O(n),⽽AVL树能保证查找操作的时间复杂度总为O(logn)。
3.avl树通过单旋转或者双旋转来实现保证树的平衡avl树和伸展树有很多相似之处,可以查看:伸展树的特点;AVL树AVL树是根据它的发明者G. M. Adelson-Velskii和E. M. Landis命名的。
它是⼀种特殊的。
AVL树要求: 任⼀节点的左⼦树深度和右⼦树深度相差不超过1(空树的深度为0。
注意,有的教材中,采⽤了不同的深度定义⽅法,所以空树的深度为-1)下⾯是AVL树:AVL树AVL树的特性让⼆叉搜索树的节点实现平衡(balance):节点相对均匀分布,⽽不是偏向某⼀侧。
因此,AVL树的搜索算法复杂度是log(n)的量级。
我们在中定义的操作,除了插⼊,都可以⽤在AVL树上 (假设使⽤懒惰删除)。
如果进⾏插⼊操作,有可能会破坏AVL树的性质,⽐如:插⼊2: 破坏AVL树观察节点5,它的左⼦树深度为2,右⼦树深度为0,所以左右两个⼦树深度相差为2,不再是AVL树。
由于2的加⼊,从节点6,1,5,3到2的层数都增加1。
6, 1, 5节点的AVL性质都被破坏。
如果从节点2向上回溯,节点5是第⼀个被破坏的。
从节点3开始的⼦树深度加1,这是造成6, 1, 5的AVL性质被破坏的本质原因。
我们将5和3之间的路径画成虚线(就好像挂了重物,边被拉断⼀样)。
我们可以通过单旋转(single rotation),调整以5为根节点的⼦树,来修正因为插⼊⼀个元素⽽引起的对AVL性质的破坏。
如下:Single rotation: 左侧超重,向右转通过单旋转,3成为新的根节点,2,5称为3的左右⼦节点。
第9章查找一、单选题1.对一棵二叉搜索树按〔〕遍历,可得到结点值从小到大的排列序列。
A. 先序B. 中序C. 后序D. 层次2.从具有n个结点的二叉搜索树中查找一个元素时,在平均情况下的时间复杂度大致为〔〕。
A. O(n)B. O(1)C. O(logn)D. O(n2)3.从具有n个结点的二叉搜索树中查找一个元素时,在最坏情况下的时间复杂度为〔〕。
A. O(n)B. O(1)C. O(logn)D. O(n2)4.在二叉搜索树中插入一个结点的时间复杂度为〔〕。
A. O(1)B. O(n)C. O(logn)D. O(n2)5.分别以下列序列构造二叉搜索树,与用其它三个序列所构造的结果不同的是〔〕。
A.〔100,80,90,60,120,110,130〕B.〔100,120,110,130,80,60,90〕C.〔100,60,80,90,120,110,130〕D.〔100,80,60,90,120,130,110〕6.在一棵AVL树中,每个结点的平衡因子的取值X围是〔〕。
A. -1~1B. -2~2C. 1~2D. 0~17.根据一组关键字〔56,42,50,64,48〕依次插入结点生成一棵A VL树,当插入到值为〔〕的结点时需要进行旋转调整。
A. 42B. 50C. 64D. 488.深度为4的A VL树至少有〔〕个结点。
A.9 B.8C.7D.69.一棵深度为k的A VL树,其每个分支结点的平衡因子均为0,则该平衡二叉树共有〔〕个结点。
A.2k-1-1B.2k-1+1C.2k-1D.2k10.在A VL树中插入一个结点后造成了不平衡,设最低的不平衡结点为A,并已知A的左孩子的平衡因子为0,右孩子的平衡因子为1,则应作〔〕型调整以使其平衡。
A. LLB. LRC. RLD. RR二、判断题1.二叉搜索树的任意一棵子树中,关键字最小的结点必无左孩子,关键字最大的结点必无右孩子。
2.二叉搜索树中每个结点的关键字值大于其左非空子树〔若存在的话〕所有结点的关键字值,且小于其右非空子树〔若存在的话〕所有结点的关键字值。
数据结构题第六章树和⼆叉树简答题1、有⼀棵树的括号表⽰为A(B,C(E,F(G)),D),回答下⾯的问题:这棵树的根结点是谁?这棵树的叶⼦结点是什么?结点C的度是多少?这棵树的度是多少?这棵树的深度是多少?结点C的孩⼦结点是哪些?结点C的双亲结点是谁?2、若⼀棵度为4的树中度为1,2,3,4的结点个数分别是4,3,2,2,则该树中叶⼦结点的个数是多少?总结点个数是多少?3、⼀棵⾼度为h的完全k次数,如果按照层次⾃上向下、⾃左向右的顺序从1开始对全部结点编号,试问:最多有多少个结点?最少有多少个结点?编号为q的结点的第i个孩⼦结点的编号是多少?4、若⼀棵⼆叉树具有10个度为2的结点,5个度为1的结点,则度为0的结点个数为结点的总个数为5、⼀棵完全⼆叉树有1001个结点,其中叶⼦结点的个数为6、⼀棵⾼度为h的完全⼆叉树⾄少有个结点。
7、⼀棵⾼度为5的完全⼆叉树⾄多有个结点。
8、设⾼度为h的⼆叉树上只有度为0和度为2的结点,则此类⼆叉树⾄少包含个结点。
9、⼀个具有1025个结点的⼆叉树的⾼度h为10、在⼀棵完全⼆叉树中,结点个数为n,则编号最⼤的分⽀结点的编号为11、⼀棵⼆叉树的先序遍历为ABCDEF,中序遍历为CBAEDF,则后序遍历为12、⼀棵⼆叉树的先序遍历为ABCDEFG,它的中序遍历可能为A.CABDEFGB. ABCDEFGC.DACEFBGD.ADCFEGB思考:⼆叉树的先序和中序遍历相同的条件是?⼆叉树的后序和中序遍历相同的条件是?13、⼀棵⼆叉树的后序遍历为DABEC,中序遍历为DEBAC,则先序遍历为14、⼀棵⼆叉树的先序遍历为EFHIGJK,中序遍历为HFIEJKG,则该⼆叉树根结点的右孩⼦为16、根据使⽤频率为5个字符设计的赫夫曼编码不可能的是A.111,110,10,01,00B.000,001,010,011,1C.100,11,10,1,0D.001,000,01,11,1017、根据使⽤频率为5个字符设计的赫夫曼编码不可能的是A. 000,001,010,011,1B.0000,0001,001,01,1C. 000,001,01,10,11D.00,100,101,110,11118、设有13个值,⽤它们组成⼀棵赫夫曼树,则该赫夫曼树共有个结点。
树的遍历题目以下是关于树的遍历的一些题目:
1. 二叉树的深度
2. 二叉树的遍历
3. 判断一棵二叉树是否为完全二叉树
4. 二叉树的层序遍历(广度优先遍历)
5. 二叉树的链式存储结构(单链表表示法)
6. 二叉树的顺序存储结构(数组表示法)
7. 二叉树的先序遍历(前序遍历)
8. 二叉树的中序遍历(中序遍历)
9. 二叉树的后序遍历(后序遍历)
10. 构建一棵二叉搜索树
11. 二叉搜索树的查找
12. 二叉搜索树的插入
13. 二叉搜索树的删除
14. 平衡二叉树(AVL树)的插入
15. 平衡二叉树(AVL树)的查找
16. 平衡二叉树(AVL树)的删除
17. 红黑树的插入
18. 红黑树的查找
19. 红黑树的删除
20. B树和B+树的查找、插入和删除操作
21. 判断一棵树是否为二叉树
22. 判断一棵树是否为满二叉树
23. 判断一棵树是否为完全二叉树
24. 判断一棵树是否为平衡二叉树
25. 判断一棵树是否为红黑树
26. 求一棵树的直径
27. 求一棵树的周长。
给予树练习题题目一:树的类型树是一种数据结构,它由节点(node)组成,节点之间存在一对多的关系。
根据节点之间的连接方式和结构特点,树可以分为以下几种类型:1. 二叉树(Binary Tree):每个节点最多有两个子节点,分别称为左子节点和右子节点。
二叉树可以为空树。
2. 二叉搜索树(Binary Search Tree):在二叉树的基础上,对于任意节点,其左子树所有节点的值都小于该节点的值,右子树所有节点的值都大于该节点的值。
3. 平衡二叉树(AVL Tree):在二叉搜索树的基础上,对于任意节点,其左子树和右子树的高度差不超过1。
4. 红黑树(Red-Black Tree):在二叉搜索树的基础上,每个节点上都有一个额外的存储位表示节点的颜色,可以是红色或黑色。
通过对任何一条从根到叶子的路径上各个节点着色的方式的约束,确保没有一条路径会比其他路径长出两倍。
题目二:树的遍历树的遍历是指按照一定的次序访问树中的每个节点,分为以下几种方式:1. 前序遍历(Preorder Traversal):先访问根节点,然后递归地前序遍历左子树,最后递归地前序遍历右子树。
2. 中序遍历(Inorder Traversal):先递归地中序遍历左子树,然后访问根节点,最后递归地中序遍历右子树。
3. 后序遍历(Postorder Traversal):先递归地后序遍历左子树,然后递归地后序遍历右子树,最后访问根节点。
4. 层序遍历(Level Order Traversal):按照从上到下、从左到右的顺序逐层访问树中的节点。
题目三:树的应用树作为一种常见的数据结构,具有广泛的应用场景,包括但不限于以下几个方面:1. 文件系统:文件系统通常使用树来组织文件的层次结构,根目录是树的根节点,每个文件夹是一个子树。
2. 数据库索引:数据库索引通常使用B树或B+树来快速查找数据,提高查询效率。
3. 编译器:编译器在语法分析阶段通常使用语法树(Syntax Tree)来表示源代码的结构,方便后续的代码生成和优化。
数据结构试题一一、单项选择题(每小题3分,共30分)1、在有n 个叶子结点的哈夫曼树中,其结点总数为()。
A、不确定B、2nC、2n+1D、2n-12、下列序列中,()是执行第一趟快速排序得到的序列(排序的关键字类型是字符串)。
A、[da,ax,eb,de,bb]ff[ha,gc]B、[cd,eb,ax,da]ff[ha,gc,bb]C、[gc,ax,eb,cd,bb]ff[da,ha] D、[ax,bb,cd,da]ff[eb,gc,ha]3、若线性表最常用的操作是存取第 i 个元素及其前驱的值,则采用()存储方式节省时间。
A、单链表B、双链表C、单循环链表D、顺序表4、下列排序算法中,时间复杂度不受数据初始状态影响,恒为O(nlogn)的是()。
A、堆排序B、冒泡排序C、直接选择排序D、快序排序5、某二叉树的先序序列和后序序列正好相反,则该二叉树一定是()的二叉树。
A、空或只有一个结点B、高度等于其结点数C、任意结点无左孩子D、任意结点无右孩子6、下列排序算法中,某一趟结束后未必能选出一个元素放在其最终位置上的是()。
A、堆排序B、冒泡排序C、直接选择排序D、快序排序7、快速排序算法在最好情况下的时间复杂度为()。
A、O(n)B、O(n 2 )C、O(nlogn)D、O(logn)8、已知数据表 A中每个元素距其最终位置不远,则采用()排序算法最省时间。
A、堆排序B、插入排序C、直接选择排序D、快序排序9、带权有向图G用邻接矩阵 A存储,则顶点 i的入度为 A中()。
A、第 i行非∞的元素之和B、第 i 列非∞的元素之和C、第 i行非∞且非 0的元素之和D、第 i 列非∞且非 0的元素之和10、在有 n个结点且为完全二叉树的二叉排序树中查找一个键值,其平均比较次数的数量级为()。
A、O(n)B、O(n 2 )C、O(nlogn)D、O(logn)二、判断题(认为对的在题后的括号内打“√”,错的打“ⅹ”,每小题1分,共10分)1.对任意一个图,从它的某个顶点出发进行一次深度优先或广度优先搜索遍历可访问该图的每个顶点。
一.实验内容分析:1.实验目的:模拟用户登录系统,在O(lgn)时间内完成用户登录、删除、修改等工作。
2.设计思路:主要分以下四个类:A VLTreeNode:存储平衡树节点;A VLTree:A VL平衡树的主要实现算法;UserInfo:存储用户信息;Interface:界面,与用户交互;3.流程图以及类的主要包含和调用关系:二.实验验证分析(1)输入的形式和输入值的范围;控制台的输入:如图,输入为数字,超出范围将提示不正确并返回重新输入文件的输入:程序会找寻当前目录的database.data文件,并读入数据,如果未找到则自创此文件,创建空树(2)输出的形式;程序退出时析构函数保存文件到database.data并覆盖原文件。
(3)程序所能达到的功能;在O(lgn)时间内添加、查找、删除、修改用户信息。
(4)测试数据:本系统包含三个测试函数样例:1.顺序插入测试(分别在debug和release环境下和STL map比较速度)2.随机插入测试(分别在debug和release环境下和STL map比较速度)3.删除测试测试函数均在main文件里void randomTest();//随机数测试void orderTest();//顺序插入测试void deleteTest();//删除测试void main_interface();//主界面1,2均在debug模式下插入100W数据,在release模式下插入1000W数据。
顺序插入的实现是用整数1~n转换为string,位数不够的在前面补‘0’。
测试结果:1.debug下顺序插入测试:2.Release下顺序插入测试3.debug下随机插入测试4.release下随机插入测试实践证明map的红黑树在顺序插入测试时慢于我的avl树,但随机插入测试表现比A VL树要好。
3.删除数据的图形化表示(‘R’‘L’‘=’为平衡因子以检验正确性)下面删除3(树中无3):还是一样,下面删除2删除成功,下面删除7删除成功。
avl树java代码实现一、什么是AVL树?AVL树是一种自平衡二叉搜索树,它的名字来自于它的发明者Adelson-Velskii和Landis。
AVL树的特点在于每个节点的左子树和右子树的高度差最多为1,这样可以保证在插入或删除节点时能够自动调整以保持平衡性。
二、AVL树的实现1. AVLNode类首先需要定义一个AVLNode类,用于表示AVL树中的节点。
每个节点包含三个属性:值val、左子节点left和右子节点right,以及一个表示该节点所在子树高度的height属性。
public class AVLNode {public int val;public AVLNode left;public AVLNode right;public int height;public AVLNode(int val) {this.val = val;this.height = 1;}}2. AVLTree类接下来定义一个AVLTree类,用于实现插入、删除等操作。
该类包含两个属性:根节点root和size(表示该AVLTree中元素数量)。
public class AVLTree {private AVLNode root;private int size;//构造函数public AVLTree() {root = null;size = 0;}3. 插入操作插入操作是向AVL树中添加新元素的过程。
由于要保持平衡性,因此需要在插入后对整棵树进行调整。
public void insert(int val) {root = insert(root, val);}private AVLNode insert(AVLNode node, int val) {if (node == null) {size++;return new AVLNode(val);}if (val < node.val) {node.left = insert(node.left, val);} else if (val > node.val) {node.right = insert(node.right, val);} else { //如果val已经存在于AVL树中,则不需要插入return node;}//更新节点高度node.height = 1 + Math.max(getHeight(node.left), getHeight(node.right));//计算平衡因子int balanceFactor = getBalanceFactor(node);//LL旋转if (balanceFactor > 1 && getBalanceFactor(node.left) >= 0) { return rightRotate(node);}//RR旋转if (balanceFactor < -1 && getBalanceFactor(node.right) <= 0) {return leftRotate(node);}//LR旋转if (balanceFactor > 1 && getBalanceFactor(node.left) < 0) { node.left = leftRotate(node.left);return rightRotate(node);}//RL旋转if (balanceFactor < -1 && getBalanceFactor(node.right) > 0) { node.right = rightRotate(node.right);return leftRotate(node);}return node;}在插入节点时,需要递归地遍历整棵树,找到插入位置。
AVL解决方案一、引言AVL(Adelson-Velsky and Landis)树是一种自平衡二叉搜索树,它保持树的高度尽可能小,以保证各种操作的平均时间复杂度为O(log n)。
本文将介绍AVL树的基本原理、性质以及如何实现一个高效的AVL解决方案。
二、AVL树的基本原理AVL树是由两位苏联数学家Adelson-Velsky和Landis于1962年提出的。
它是一种二叉搜索树,具有以下特点:1. 每个节点都有一个平衡因子(Balance Factor),定义为该节点的左子树高度减去右子树高度。
平衡因子可以为-1、0或1。
2. AVL树的任何节点的平衡因子绝对值不超过1,即平衡因子的绝对值小于等于1。
3. AVL树的每个节点的左子树和右子树都是AVL树。
三、AVL树的插入操作当向AVL树中插入一个新节点时,需要保持AVL树的平衡性。
插入操作的基本步骤如下:1. 执行二叉搜索树的插入操作,将新节点插入到合适的位置。
2. 自底向上更新每个祖先节点的平衡因子。
3. 如果发现某个节点的平衡因子绝对值超过1,则需要进行相应的旋转操作以恢复平衡。
四、AVL树的旋转操作AVL树的旋转操作有四种情况,分别是左旋、右旋、左右旋和右左旋。
旋转操作可以通过调整树的结构来保持AVL树的平衡性。
1. 左旋:当某个节点的平衡因子为2,且其右子树的平衡因子为1或0时,进行左旋操作。
2. 右旋:当某个节点的平衡因子为-2,且其左子树的平衡因子为-1或0时,进行右旋操作。
3. 左右旋:当某个节点的平衡因子为2,且其右子树的平衡因子为-1时,进行左右旋操作。
4. 右左旋:当某个节点的平衡因子为-2,且其左子树的平衡因子为1时,进行右左旋操作。
五、AVL树的删除操作当从AVL树中删除一个节点时,同样需要保持AVL树的平衡性。
删除操作的基本步骤如下:1. 执行二叉搜索树的删除操作,找到要删除的节点。
2. 自底向上更新每个祖先节点的平衡因子。
第8章 搜索
8-1 设有序顺序表中的元素依次为017, 094,
154, 170, 275, 503, 509, 512, 553, 612, 677, 765, 897, 908。试画出对其进行折半搜索时的二叉搜索树, 并计算搜索成功的平均搜索长度和搜索不成功的平均搜索长度。 【解答】 509 154 677 553 897 017 275 094 170 503 512
612 765 908 141145ASLC(12*23*44*7)
succi141414i1151159'C(3*14*14)ASL
iunsucc151515i0 8-2 若对有n个元素的有序顺序表和无序顺序表进行顺序搜索, 试就下列三种情况分别讨论两者在等搜索概率时的平均搜索长度是否相同? (1) 搜索失败; (2) 搜索成功, 且表中只有一个关键码等于给定值k的对象; (3) 搜索成功, 且表中有若干个关键码等于给定值k的对象, 要求一次搜索找出所有对象。 【解答】 (1) 不同。因为有序顺序表搜索到其关键码比要查找值大的对象时就停止搜索,报告失败信息,不必搜索到表尾;而无序顺序表必须搜索到表尾才能断定搜索失败。 (2) 相同。搜索到表中对象的关键码等于给定值时就停止搜索,报告成功信息。 (3) 不同。有序顺序表中关键码相等的对象相继排列在一起,只要搜索到第一个就可以连续搜索到其它关键码相同的对象。而无序顺序表必须搜索全部表中对象才能确定相同关键码的对象都找了出来,所需时间就不相同了。 前两问可做定量分析。第三问推导出的公式比较复杂,不再进一步讨论。 8-3 假定用一个循环链表来实现一个有序表,并让指针head指向具有最小关键码的结点。指针current初始时等于head,每次搜索后指向当前检索的结点,但如果搜索不成功则current重置为head。试编写一个函数search(head, current, key)实现这种搜索。当搜索成功时函数返回被检索的结点地址,若搜索不成功则函数返回空指针0。请说明如何保持指针current以减少搜索时的平均搜索长度。 【解答】 current 10 20 30 40 50 60 head 相应的搜索函数可以定义为链表及链表结点类的友元函数,直接使用链表及链表结点类的私有数据成员。 80
数据结构:AVL树⼆叉查找树的⼀个局限性就是有可能退化成⼀个链表,这种情况下⼆叉查找树的效率就会急剧下降变成0(n)。
⽽AVL树可以很好地解决BST的这种困境。
本篇博客会介绍AVL树的基本特点和相关操作。
⽂章参考⾃博客:1. 什么是AVL树任何两个⼦树的⾼度差最⼤是1,这样的⼆叉树叫做AVL树。
先来确定⼏个概念:平衡因⼦:将⼆叉树上节点的左⼦树⾼度减去右⼦树⾼度的值称为该节点的平衡因⼦BF(Balance Factor)。
最⼩不平衡⼦树:距离插⼊节点最近的,且平衡因⼦的绝对值⼤于1的节点为根的⼦树。
左边⼆叉树的节点45的BF = 1,插⼊节点43后,节点45的BF=2。
节点45是距离插⼊点43最近的BF不在[-1,1]范围内的节点,因此以节点45为根的⼦树为最⼩不平衡⼦树。
2. 节点的实现public class AVLTreeNode<T extends Comparable> {// 存储的数据-⽤于排序T key;// 节点⾼度-⽤于计算⽗节点的BFint height;// 左⼉⼦ & 右⼉⼦AVLTreeNode<T> left;AVLTreeNode<T> right;public AVLTreeNode() {}public AVLTreeNode(T key, AVLTreeNode<T> left, AVLTreeNode<T> right) {this.key = key;this.left = left;this.right = right;this.height = 0;}}节点的定义还是⽐较简单的,相对于之前的定义多了⼀个height属性⽤于计算⽗节点的BF。
树的定义public class AVLTree<T extends Comparable> {// 定义树的根节点AVLTreeNode<T> root;public AVLTree() {root = null;}}获取树的⾼度public int height() {return height(root);}private int height(AVLTreeNode<T> tree) {if (tree != null){return tree.height;}return 0;}本⽂章将空树的⾼度定义为0,⾼度以树的层次为准,根节点的⾼度为1,依次类推。
数据结构九:AVL树(O(logn))AVL树来自"NOCOW"跳转到: 导航, 搜索本文在GNU自由文档许可证之条款下提供在计算机科学中,AVL树是最先发明的自平衡二叉查找树。
在AVL树中任何节点的两个儿子子树的高度最大差别为一,所以它也被称为高度平衡树。
查找、插入和删除在平均和最坏情况下都是O(log n)。
增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。
AVL树得名于它的发明者 G.M. Adelson-Velsky 和 E.M. Landis,他们在1962年的论文"An algorithm for the organization of information" 中发表了它。
节点的平衡因子是它的右子树的高度减去它的左子树的高度。
带有平衡因子 1、0 或 -1 的节点被认为是平衡的。
带有平衡因子 -2 或 2 的节点被认为是不平衡的,并需要重新平衡这个树。
平衡因子可以直接存储在每个节点中,或从可能存储在节点中的子树高度计算出来。
目录[隐藏]•1操作o 1.1插入o 1.2删除o 1.3查找•2参考实现•3使用高度替代平衡因子•4平衡因子的推算[编辑] 操作AVL树的基本操作一般涉及运做同在不平衡的二叉查找树所运做的同样的算法。
但是要进行预先或随后做一次或多次所谓的"AVL 旋转"。
假设由于在二叉排序树上插入结点而失去平衡的最小子树根结点的指针为a(即a是离插入点最近,且平衡因子绝对值超过1的祖先结点),则失去平衡后进行进行的规律可归纳为下列四种情况:1.单向右旋平衡处理RR:由于在*a的左子树根结点的左子树上插入结点,*a的平衡因子由1增至2,致使以*a为根的子树失去平衡,则需进行一次右旋转操作;2.单向左旋平衡处理LL:由于在*a的右子树根结点的右子树上插入结点,*a的平衡因子由-1变为-2,致使以*a为根的子树失去平衡,则需进行一次左旋转操作;3.双向旋转(先左后右)平衡处理LR:由于在*a的左子树根结点的右子树上插入结点,*a的平衡因子由1增至2,致使以*a为根的子树失去平衡,则需进行两次旋转(先左旋后右旋)操作。