数据结构之AVL树

合集下载

关于数据结构树的举例

关于数据结构树的举例

关于数据结构树的举例
树是一种常见的数据结构,它有根节点、子节点和叶节点组成。

树的一个重要特点是它可以表达具有层次结构的数据。

以下是一些关于数据结构树的举例:
1. 二叉树:每个节点最多有两个子节点的树结构。

一种常见的应用是二叉搜索树,其中左子节点的值小于父节点的值,右子节点的值大于父节点的值。

2. AVL树:一种自平衡二叉搜索树,用于解决普通二叉搜索
树可能导致的不平衡问题。

AVL树通过旋转操作来使树保持
平衡。

3. 红黑树:另一种自平衡二叉搜索树,也用于解决二叉搜索树可能导致的不平衡问题。

红黑树通过颜色标记节点并进行旋转操作来保持平衡。

4. B树:一种用于在外部存储中组织大量数据的数据结构。

B
树具有多个子节点和键值对,并且在每个节点上有更多的子节点,以减少I/O操作。

5. 堆:一种特殊的树结构,用于快速访问最大或最小元素。

在大根堆中,父节点的值大于或等于子节点的值;在小根堆中,父节点的值小于或等于子节点的值。

6. 树状数组:一种特殊的树结构,用于高效地进行前缀和查询和更新操作。

树状数组通常用于解决区间求和等相关问题。

7. Trie树:一种用于存储和搜索字符串的数据结构。

Trie树逐
个字符存储字符串,并通过每个节点的子节点表示不同的字符。

这些只是数据结构树的一些常见例子,还有许多其他类型的树结构可用于各种应用。

二叉树的自平衡

二叉树的自平衡

二叉树的自平衡
自平衡二叉树是一种特殊的二叉查找树(Binary Search Tree,BST),它在插入或删除节点时能够自动调整树的结构,以保持树的平衡性。

平衡性的维护有助于确保在查找、插入和删除等操作时,树的性能保持在较高水平。

常见的自平衡二叉树包括:
1.A VL树:A VL树是一种最早被发明的自平衡二叉树。

在A VL树中,任意节点的左右子树高度之差(平衡因子)不能超过1。

当进行插入或删除操作后,如果破坏了平衡性,A VL树会通过旋转操作(左旋或右旋)来重新平衡。

2.红黑树:红黑树是一种更为灵活的自平衡二叉树。

在红黑树中,每个节点都被标记为红色或黑色,并通过一些规则确保树的平衡性。

这些规则包括节点颜色的变换和树的旋转。

3.Splay树:Splay树在每次访问一个节点后,将该节点移动到树的根位置,以提高后续对该节点的访问速度。

Splay树不维持固定的平衡条件,但通过频繁的局部调整来实现整体的平衡。

4.Treap(树堆):Treap是一种随机化的自平衡二叉树,结合了二叉搜索树和堆的性质。

每个节点有一个随机的优先级值,通过调整节点的优先级和执行旋转来保持树的平衡。

这些自平衡二叉树的设计灵感各异,选择适当的树取决于应用的具体要求。

自平衡二叉树的主要优势是保持较低的查找、插入和删除操作的时间复杂度,使其在很多应用中都是一个有用的数据结构。

各种二叉树的介绍

各种二叉树的介绍

各种二叉树的介绍
二叉树是一种常见的数据结构,每个节点最多只能有两个子节点,通常称为左子节点和右子节点。

根据二叉树的不同特性和限制,可以将其分为多种类型,包括普通二叉树、满二叉树、完全二叉树、平衡二叉树等。

普通二叉树:这是最基本的二叉树形式,每个节点最多有两个子节点,且没有特定的限制条件。

满二叉树:在满二叉树中,所有叶子节点都在最后一层,且节点总数为2^n-1,其中n为层数。

也就是说,除了叶子节点外,每个节点都有两个子节点。

完全二叉树:完全二叉树的所有叶子节点都在最后一层或倒数第二层,且最后一层的叶子节点在左边连续,倒数第二层的叶子节点在右边连续。

如果将满二叉树从右至左、从下往上删除一些节点,剩余的结构就构成完全二叉树。

平衡二叉树(AVL树):平衡二叉树是一种特殊的二叉树,它要求每个节点的左子树和右子树的高度差绝对值不超过1,且每个子树也必须是一棵平衡二叉树。

这种树的查找效率通常高于普通二叉树,因此常用于需要频繁查找的场景。

此外,还有一些特殊的二叉树,如红黑树、B树、B+树等,它们具有不同的特性和应用场景。

红黑树是一种自平衡的二叉查找树,它的左右子树高度差有可能大于1,但通过对节点进行旋转和重新着色等操作,可以保持树的平衡性。

B树和B+树则常用于数据库和文件系统中,它们支持对节点进行分裂和合并操作,以满足快速查找、插入和删除数据的需求。

总之,二叉树是一种非常有用的数据结构,它可以用于实现各种算法和应用,如排序、搜索、压缩、加密等。

不同类型的二叉树具有不同的特性和应用场景,需要根据具体需求进行选择和使用。

数据结构之二叉树(BinaryTree)

数据结构之二叉树(BinaryTree)

数据结构之⼆叉树(BinaryTree)⽬录导读 ⼆叉树是⼀种很常见的数据结构,但要注意的是,⼆叉树并不是树的特殊情况,⼆叉树与树是两种不⼀样的数据结构。

⽬录 ⼀、⼆叉树的定义 ⼆、⼆叉树为何不是特殊的树 三、⼆叉树的五种基本形态 四、⼆叉树相关术语 五、⼆叉树的主要性质(6个) 六、⼆叉树的存储结构(2种) 七、⼆叉树的遍历算法(4种) ⼋、⼆叉树的基本应⽤:⼆叉排序树、平衡⼆叉树、赫夫曼树及赫夫曼编码⼀、⼆叉树的定义 如果你知道树的定义(有限个结点组成的具有层次关系的集合),那么就很好理解⼆叉树了。

定义:⼆叉树是n(n≥0)个结点的有限集,⼆叉树是每个结点最多有两个⼦树的树结构,它由⼀个根结点及左⼦树和右⼦树组成。

(这⾥的左⼦树和右⼦树也是⼆叉树)。

值得注意的是,⼆叉树和“度⾄多为2的有序树”⼏乎⼀样,但,⼆叉树不是树的特殊情形。

具体分析如下⼆、⼆叉树为何不是特殊的树 1、⼆叉树与⽆序树不同 ⼆叉树的⼦树有左右之分,不能颠倒。

⽆序树的⼦树⽆左右之分。

2、⼆叉树与有序树也不同(关键) 当有序树有两个⼦树时,确实可以看做⼀颗⼆叉树,但当只有⼀个⼦树时,就没有了左右之分,如图所⽰:三、⼆叉树的五种基本状态四、⼆叉树相关术语是满⼆叉树;⽽国际定义为,不存在度为1的结点,即结点的度要么为2要么为0,这样的⼆叉树就称为满⼆叉树。

这两种概念完全不同,既然在国内,我们就默认第⼀种定义就好)。

完全⼆叉树:如果将⼀颗深度为K的⼆叉树按从上到下、从左到右的顺序进⾏编号,如果各结点的编号与深度为K的满⼆叉树相同位置的编号完全对应,那么这就是⼀颗完全⼆叉树。

如图所⽰:五、⼆叉树的主要性质 ⼆叉树的性质是基于它的结构⽽得来的,这些性质不必死记,使⽤到再查询或者⾃⼰根据⼆叉树结构进⾏推理即可。

性质1:⾮空⼆叉树的叶⼦结点数等于双分⽀结点数加1。

证明:设⼆叉树的叶⼦结点数为X,单分⽀结点数为Y,双分⽀结点数为Z。

平衡二叉树

平衡二叉树
2算法
编辑
红黑树
红黑树是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。它是在1972年由Rudolf Bayer发明的,他称之为"对称二叉B树",它现代的名字是在 Leo J. Guibas 和 Robert Sedgewick 于1978年写的一篇论文中获得的。它是复杂的,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n是树中元素的数目。
伸展树
伸展树(Splay Tree)是一种二叉排序树,它能在O(log n)内完成插入、查找和删除操作。它由Daniel Sleator和Robert Tarjan创造。它的优势在于不需要记录用于平衡树的冗余信息。在伸展树上的一般操作都基于伸展操作。
SBT
Size Balanced Tree(简称SBT)是一自平衡二叉查找树,是在计算机科学中用到的一种数据结构。它是由中国广东中山纪念中学的陈启峰发明的。陈启峰于2006年底完成论文《Size Balanced Tree》,并在2007年的全国青少年信息学奥林匹克竞赛冬令营中发表。由于SBT的拼写很容易找到中文谐音,它常被中国的信息学竞赛选手和ACM/ICPC选手们戏称为“傻B树”、“Super BT”等。相比红黑树、AVL树等自平衡二叉查找树,SBT更易于实现。据陈启峰在论文中称,SBT是“目前为止速度最快的高级二叉搜索树”。SBT能在O(log n)的时间内完成所有二叉搜索树(BST)的相关操作,而与普通二叉搜索树相比,SBT仅仅加入了简洁的核心操作Maintain。由于SBT赖以保持平衡的是size域而不是其他“无用”的域,它可以很方便地实现动态顺序统计中的select和rank操作。

AVL树与B树的比较数据结构中的平衡树对比

AVL树与B树的比较数据结构中的平衡树对比

AVL树与B树的比较数据结构中的平衡树对比在数据结构中,平衡树是一种常见的数据结构,用于在插入和删除操作时保持树的平衡,以确保检索效率。

AVL树和B树都是常见的平衡树结构,它们在不同场景下有着各自的优势和特点。

本文将对AVL 树和B树进行比较,探讨它们在数据结构中的应用和区别。

### AVL树AVL树是一种自平衡二叉搜索树,它的特点是任意节点的左右子树高度差不超过1。

当在AVL树中进行插入或删除操作时,系统会通过旋转操作来保持树的平衡。

AVL树的平衡性能较好,适用于对读操作较多的场景。

#### 优点1. **平衡性好**:AVL树能够保持树的平衡,确保检索效率稳定。

2. **适用于静态数据集**:适合对静态数据集进行频繁的搜索操作。

#### 缺点1. **频繁的旋转操作**:在插入和删除操作时,可能需要频繁进行旋转操作,影响性能。

2. **空间需求较大**:由于需要存储额外的平衡因子,占用的空间较大。

### B树B树是一种多路搜索树,常用于文件系统和数据库中。

B树的特点是每个节点可以包含多个子节点,节点中的关键字按顺序排列。

B树的平衡性是通过调整节点的大小和结构来实现的,适用于对写操作较多的场景。

#### 优点1. **适用于磁盘存储**:B树适合在磁盘存储中进行数据检索,减少磁盘I/O次数。

2. **写操作效率高**:B树的平衡性能较好,适合对数据频繁进行插入和删除操作。

#### 缺点1. **平衡性相对较差**:相比AVL树,B树的平衡性能略逊一筹。

2. **节点结构复杂**:B树的节点结构较为复杂,实现和维护相对困难。

### AVL树与B树的比较1. **平衡性能**:AVL树的平衡性能优于B树,适合对静态数据集进行频繁的搜索操作;而B树适合对写操作较多的场景,能够减少磁盘I/O次数。

2. **空间需求**:AVL树由于需要存储额外的平衡因子,空间需求较大;而B树的节点结构较为复杂,实现和维护相对困难。

2024年度如何学习AVL

2024年度如何学习AVL

文件系统
在文件系统中,目录结构通常采用类似AVL树的平衡树结构,以便快速定位文件或目录。这种结构可以保持文件 系统的平衡,提高文件访问速度。
2024/3/23
18
数据动态变化且需保持有序场景
实时数据处理
在实时数据处理系统中,数据会不断动态变化。使用AVL树可以确保数据在插 入、删除等操作后仍然保持有序,便于进行实时分析和处理。
LR旋转(先左旋 后右旋)
RL旋转(先右旋 后左旋)
当在左子树的右子树中 插入新节点导致平衡因 子失衡时,进行LR旋转 。具体操作为先将失衡 节点的左子树进行左旋 操作,再将失衡节点进 行右旋操作。
当在右子树的左子树中 插入新节点导致平衡因 子失衡时,进行RL旋转 。具体操作为先将失衡 节点的右子树进行右旋 操作,再将失衡节点进 行左旋操作。
初始化AVL树
将根节点指针指向空节点 ,表示AVL树为空。
12
插入、删除操作代码实现
插入操作
从根节点开始,按照二叉搜索树的规则找到插入 位置。
更新插入路径上所有节点的高度。
2024/3/23
13
插入、删除操作代码实现
• 检查是否需要进行平衡调整,若需要则进 行相应的旋转操作。
2024/3/23
14
01
《算法导论》(Introduction to Algorithms):这本经典教材 深入浅出地介绍了各种算法和数据结构,包括AVL树。它既有严 谨的理论分析,也提供了大量的实例和习题,是学习AVL的必备 参考书。
2024/3/23
02 03
《数据结构与算法分析》(Data Structures and Algorithm Analysis in Java):这本书详细讲解了如何 使用Java实现各种数据结构和算法,其中也包括AVL树。 它通过实例和图表帮助读者更好地理解AVL树的原理和实 现。

avl的引入流程

avl的引入流程

avl的引入流程AVL树是一种自平衡二叉树,它通过旋转操作来保持树的平衡,确保任何节点的左子树和右子树的高度差最多为1、在引入AVL树的过程中,需要进行如下几个步骤:1.引入背景:首先,我们需要说明引入AVL树的背景和初衷。

AVL树的概念最早由G.M. Adelson-Velsky和E.M. Landis在1962年提出,他们希望通过这种数据结构来提高和插入操作的平均和最糟糕情况下的时间复杂度。

2.定义:接下来,我们需要定义AVL树的性质和操作。

AVL树是一种二叉树,它具有以下几个特点:-每个节点最多有两个子节点。

-左子树和右子树的高度差最多为1-每个节点的值大于其左子树中所有节点的值,小于其右子树中所有节点的值。

3.插入操作:在向AVL树中插入新节点时,需要进行一系列的旋转操作来保持树的平衡。

插入操作的过程如下:-首先,我们需要将新节点插入到合适的位置,使得树仍然保持二叉树的性质。

-然后,我们从插入点开始向上遍历,检查每个祖先节点是否平衡。

如果祖先节点不平衡,需要进行旋转操作来调整平衡。

-旋转操作分为两种类型:左旋和右旋。

左旋可以平衡右子树比左子树高的情况,右旋可以平衡左子树比右子树高的情况。

通过旋转操作,我们可以将不平衡的子树转换为平衡的子树。

-当所有祖先节点都平衡时,整个插入操作完成。

4.删除操作:在从AVL树中删除节点时,也需要进行一系列的旋转操作来保持树的平衡。

删除操作的过程如下:-首先,我们需要找到要删除的节点。

如果节点不存在,则删除操作完成。

-如果要删除的节点有两个子节点,可以选择用其前驱或后继节点替换它,并将要删除的节点变为其前驱或后继节点。

-删除节点后,我们需要从删除点开始向上遍历,检查每个祖先节点是否平衡。

如果祖先节点不平衡,需要进行旋转操作来调整平衡。

-同样,旋转操作分为左旋和右旋,以调整平衡。

-当所有祖先节点都平衡时,整个删除操作完成。

5.性能分析:最后,我们需要对AVL树的性能进行分析。

AVL树的最少节点数

AVL树的最少节点数

AVL树的最少节点数AVL树的最少节点数今天考试数据结构考试前有这么道题:⾼为h 的AVL(平衡⼆叉树)⾄少有⼏个节点。

但是可是给我难住了,当时真是眼前⼀蒙,但是⾃⼰还是迎着头⽪钻研了⼀下,做出来了结果⾸先,avl树的节点个数怎么计算第⼀我们画出来⼀层的也就是只有⼀个节点然后画出来两层的两个节点以上都是⾄少所以后来我们计算有三层的时候,可以增加⼀个节点A,A的左⼦树就是两层的⾄少得情况右⼦树就是⼀层的情况,这样全部就是平衡的情况,⽽且数⽬最少,同时还满⾜平衡⼆叉树的条件:即左右⼦树的⾼度差不超过1.这样我们得到了递推公式A(n+2)=A(n+1)+A(n)+1; 1式A(n+3)=A(n+2)+A(n+1)+1; 2式数学⾥⾯学过特征根⽅程在数列求解递推公式和求解时候⽤到这⾥就不再赘述了,⾼中数学知识2式减1式,得出来B(n+2)=B(n+1)+B(n);就是著名的斐波那契数列最后求得就是这个东西⽽A(n+1)-A(n)=B(n);就是说在求出来A就好了根据特征根的有x2=x+1求出来的特征根满⾜B n=sa1n+Ta2n这时,带⼊b1=1,b2=2得到结果是s=55+5然后求得A时候有A n?A n?1=B n?1A n?1?A n?2=B n?2……A2?A1=B1叠加起来就是对左边求和A=3+55+51?1+52n?11+523?55?51?1?52n?11?52+1在这⾥求和结果就不再化简了这⾥就是对结果进⾏了计算机的模拟贴出来模拟结果如下只显⽰前10项这个结果在百度维基百科上⾯也能查到,就是斐波那契数列的后⼀项减去1写出我们写的斐波那契数列结果5 5+5×1+5n+1+55?5×1?5n+11附代码如下(C++)#include#includeusingnamespace std;constlongdouble g=sqrt((longdouble)5);//表⽰根号5constlongdouble S=(3+g)/(5+g); constlongdouble T=(3-g)/(5-g); constlongdouble a1=(1+g)/2; constlongdouble a2=(1-g)/2; longdouble Bn(int n){longdouble aaa,bbb;aaa=pow(a1,(longdouble)n);bbb=pow(a2,(longdouble)n);return S*aaa+T*bbb;}longdouble An(int n){longdouble aaa,bbb;aaa=(1-pow(a1,(longdouble)n-1))/(1-a1);bbb=(1-pow(a2,(longdouble)n-1))/(1-a2);return S*aaa*a1+T*bbb*a2+1;}int main(){for (int i=1;i<11;i++)//控制输出的数据个数{cout<}cout<for (int i=1;i<11;i++){cout<}cout<}。

AVL树了解AVL树的平衡性和旋转操作

AVL树了解AVL树的平衡性和旋转操作

AVL树了解AVL树的平衡性和旋转操作AVL树,全称Adelson-Velsky-Landis树,是一种经典的自平衡二叉搜索树。

在AVL树中,任意节点的左子树和右子树的高度差不超过1,这保证了树的平衡性。

为了维持平衡,AVL树在插入和删除节点时,会通过旋转操作来调整树的结构。

下面我们将了解AVL树的平衡性以及旋转操作的原理和步骤。

一、AVL树的平衡性AVL树的平衡性是指树的任意节点的左子树和右子树的高度差不超过1。

为了实现这种平衡性,AVL树的节点需要存储每个子树的高度信息,并在插入和删除节点时,通过旋转操作来调整树的结构,以维持平衡。

二、旋转操作的原理和步骤旋转操作是AVL树用来调整结构的主要方法,分为左旋和右旋两种。

下面我们将详细介绍这两种旋转操作的原理和步骤。

1. 左旋左旋操作是指将当前节点的右子节点上移,当前节点成为新的左子节点。

左旋操作的原理如下:(1)将当前节点的右子节点的左子节点作为当前节点的右子节点;(2)将当前节点的右子节点作为新的根节点;(3)将当前节点作为右子节点的左子节点。

左旋操作的步骤如下:(1)判断当前节点是否有右子节点,若没有,则无法进行左旋操作;(2)保存当前节点的右子节点,并将右子节点的左子节点设置为当前节点的右子节点;(3)将当前节点的右子节点设为右子节点的左子节点;(4)将右子节点设为当前节点的左子节点;(5)更新当前节点和右子节点的高度信息。

2. 右旋右旋操作是指将当前节点的左子节点上移,当前节点成为新的右子节点。

右旋操作的原理如下:(1)将当前节点的左子节点的右子节点作为当前节点的左子节点;(2)将当前节点的左子节点作为新的根节点;(3)将当前节点作为左子节点的右子节点。

右旋操作的步骤如下:(1)判断当前节点是否有左子节点,若没有,则无法进行右旋操作;(2)保存当前节点的左子节点,并将左子节点的右子节点设置为当前节点的左子节点;(3)将当前节点的左子节点设为左子节点的右子节点;(4)将左子节点设为当前节点的右子节点;(5)更新当前节点和左子节点的高度信息。

AVL树与红黑树的比较与应用

AVL树与红黑树的比较与应用

AVL树与红黑树的比较与应用AVL树和红黑树是两种常见的自平衡二叉搜索树,它们在计算机科学领域被广泛应用于实现高效的数据结构和算法。

本文将对AVL树和红黑树进行比较,并探讨它们在不同场景下的应用。

一、AVL树与红黑树的定义AVL树是一种高度平衡的二叉搜索树,它要求任意节点的左子树和右子树的高度差不超过1。

而红黑树是一种近似平衡的二叉搜索树,它通过引入颜色标记和一些特定规则来保持整棵树的平衡。

二、AVL树与红黑树的比较1. 平衡性:AVL树保持严格的平衡,任意节点的左右子树高度差不超过1,因此在查找、插入和删除操作时,AVL树的平均时间复杂度为O(logn)。

而红黑树虽然不要求严格的平衡,但通过引入颜色标记和旋转操作,能够保持整棵树的近似平衡,因此在实际应用中,红黑树的性能也非常优秀。

2. 结构复杂度:AVL树的平衡性要求更为严格,因此在插入和删除操作时,可能需要进行多次旋转操作来调整树的结构,这会导致性能的一定损耗。

而红黑树通过引入颜色标记和一些特定规则,能够在插入和删除操作时保持树的平衡,旋转操作次数相对较少,性能相对更优。

3. 应用场景:由于AVL树的平衡性要求更为严格,适合于对插入和删除操作次数相对较少的场景,例如数据库索引。

而红黑树由于其结构相对简单,适合于对插入和删除操作次数较多的场景,例如C++ STL中的map和set容器。

三、AVL树与红黑树的应用1. AVL树的应用:AVL树由于其严格的平衡性,在需要快速查找、插入和删除操作的场景中得到广泛应用。

例如,在数据库系统中,AVL树常被用作索引结构,能够快速定位到需要的数据记录。

此外,在编译器的符号表实现、路由表查找等领域,AVL树也有着重要的应用价值。

2. 红黑树的应用:红黑树由于其结构相对简单且性能优秀,在实际应用中被广泛使用。

例如,在C++ STL中,map和set容器的底层实现就是红黑树。

此外,在Linux内核中,红黑树也被广泛应用于进程调度、定时器管理等模块中,发挥着重要作用。

名词解释平衡二叉树

名词解释平衡二叉树

平衡二叉树介绍平衡二叉树(Balanced Binary Tree),简称AVL树,是一种特殊的二叉搜索树。

在平衡二叉树中,任意节点的左子树和右子树的高度之差不超过1。

这种平衡性的特点使得平衡二叉树的查找、插入和删除操作的时间复杂度保持在O(log n)级别,极大地提高了数据结构的效率。

定义和性质平衡二叉树是一种特殊的二叉搜索树,满足以下性质: 1. 空树或者任意节点的左右子树高度之差的绝对值不超过1。

2. 左子树和右子树都是平衡二叉树。

对于平衡二叉树,我们还可以得出一些重要的结论: 1. 平衡二叉树的任意节点的左子树和右子树的高度差不超过1。

也就是说,平衡二叉树的高度是一个较小的常数倍数。

2. 平衡二叉树的最小高度是log n,最大高度是2log n。

实现方法为了保持二叉树的平衡,我们需要对插入和删除操作进行适当的调整。

下面介绍两种常见的平衡二叉树实现方法。

AVL树AVL树是最早提出的平衡二叉树之一。

在AVL树中,每个节点都会存储一个额外的信息,即平衡因子(balance factor)。

平衡因子的定义是左子树的高度减去右子树的高度。

如果平衡因子的绝对值大于1,就需要进行平衡调整。

AVL树的平衡调整分为四种情况:左-左旋转(LL),右-右旋转(RR),左-右旋转(LR),和右-左旋转(RL)。

通过这四种旋转操作,可以使得树重新达到平衡状态。

红黑树红黑树是另一种常见的平衡二叉树。

红黑树的平衡调整是通过变换节点的颜色和旋转节点来完成的。

红黑树的规则如下: 1. 每个节点要么是红色,要么是黑色。

2. 根节点是黑色。

3. 所有叶子节点(NIL节点)都是黑色。

4. 如果一个节点是红色的,则它的两个子节点都是黑色的。

5. 任意节点到其每个叶子节点的路径上包含相同数目的黑色节点。

通过对节点进行颜色变换和旋转操作,红黑树可以在插入和删除节点的过程中保持平衡。

平衡二叉树的应用平衡二叉树在计算机科学中有广泛的应用。

数据结构——用C语言描述 第六章 树状结构

数据结构——用C语言描述  第六章 树状结构

数据结构——用C语言描述第六章树状结构在计算机科学中,数据结构是组织和存储数据的方式,以便能够高效地访问和操作这些数据。

树状结构是一种重要的数据结构,它在许多算法和应用中都发挥着关键作用。

树状结构就像是一棵倒立的树,有一个根节点,然后从根节点向下延伸出许多分支,每个分支又可以进一步延伸出更多的分支。

这种结构使得数据的组织和管理更加清晰和高效。

在树状结构中,每个节点可以包含数据以及指向其子节点的指针。

节点之间通过这些指针形成层次关系。

树状结构的一个重要特点是,除了根节点外,每个节点都有且仅有一个父节点。

二叉树是树状结构中最常见的一种形式。

二叉树中的每个节点最多有两个子节点,分别称为左子节点和右子节点。

二叉搜索树是一种特殊的二叉树,它具有一定的规则。

对于二叉搜索树中的每个节点,其左子树中的所有节点的值都小于该节点的值,而其右子树中的所有节点的值都大于该节点的值。

这种特性使得在二叉搜索树中进行查找、插入和删除操作的效率很高。

例如,如果要在二叉搜索树中查找一个值,我们可以从根节点开始。

如果要查找的值小于当前节点的值,就向左子树继续查找;如果大于当前节点的值,就向右子树继续查找。

直到找到目标值或者确定该值不存在。

用 C 语言来实现二叉搜索树,首先需要定义一个节点结构体,来存储节点的数据以及左右子节点的指针。

```ctypedef struct TreeNode {int data;struct TreeNode left;struct TreeNode right;} TreeNode;```接下来,实现插入节点的函数。

插入节点时,需要按照二叉搜索树的规则,找到合适的位置插入新节点。

```cvoid insertNode(TreeNode root, int value) {if (root == NULL) {root =(TreeNode )malloc(sizeof(TreeNode));(root)>data = value;(root)>left = NULL;(root)>right = NULL;return;}if (value <(root)>data) {insertNode(&((root)>left), value);} else if (value >(root)>data) {insertNode(&((root)>right), value);}}```查找节点的函数也类似,根据比较值的大小在左右子树中递归查找。

AVL树数据结构的特点与使用场景

AVL树数据结构的特点与使用场景

AVL树数据结构的特点与使用场景AVL树是一种自平衡的二叉搜索树,它在插入或删除节点时会通过旋转操作来保持树的平衡,以确保树的高度始终保持在较小的范围内。

AVL树得名于其发明者Adelson-Velsky和Landis,是一种高度平衡的二叉搜索树,具有快速的查找、插入和删除操作的特点。

在本文中,将介绍AVL树数据结构的特点以及其在实际应用中的使用场景。

一、AVL树的特点1. 自平衡性:AVL树是一种自平衡的二叉搜索树,任何时刻,AVL 树的任意节点的左右子树的高度差不超过1。

当插入或删除节点后,AVL树会通过旋转操作来保持树的平衡,以确保树的高度始终保持在较小的范围内,从而保证了查找、插入和删除操作的时间复杂度为O(log n)。

2. 高度平衡:由于AVL树的自平衡性,使得树的高度相对较低,这样在进行查找操作时,平均查找时间较短,提高了搜索效率。

3. 严格平衡:AVL树是一种严格平衡的二叉搜索树,任何时刻,AVL树的任意节点的左右子树的高度差不超过1,这种严格平衡性保证了AVL树的高度始终保持在较小的范围内,使得其在各种操作下都能保持高效性。

4. 插入和删除操作复杂度低:由于AVL树的自平衡性,插入和删除节点时需要进行旋转操作来保持树的平衡,但这些旋转操作的时间复杂度为O(log n),因此插入和删除操作的复杂度仍然为O(log n),保证了操作的高效性。

二、AVL树的使用场景1. 数据库索引:在数据库系统中,AVL树常被用作索引结构,用于加速数据库的查找操作。

由于AVL树具有快速的查找、插入和删除操作,能够保持树的平衡,因此在数据库索引中得到广泛应用。

2. 编辑器中的自动补全功能:在文本编辑器或代码编辑器中,常常需要实现自动补全功能,AVL树可以用来存储单词或代码片段,通过快速查找实现自动补全功能,提高编辑效率。

3. 路由表:在网络路由中,需要快速查找目标地址对应的路由信息,AVL树可以用来存储路由表,通过快速查找实现高效的路由转发,提高网络传输效率。

原题目:比较二叉树和AVL树的区别。

原题目:比较二叉树和AVL树的区别。

原题目:比较二叉树和AVL树的区别。

原题目:比较二叉树和AVL树的区别
二叉树和AVL树是常用的数据结构,它们都是树形结构,但
在某些方面有一些区别。

1. 定义:
- 二叉树:每个节点最多有两个子节点的树结构。

- AVL树:也是一种二叉搜索树,但它具有自平衡特性。

2. 平衡特性:
- 二叉树:二叉树没有保持平衡的要求,所以可能出现不平衡
的情况。

- AVL树:AVL树要求在插入或删除节点后,保持树的平衡状态。

每个节点的左右子树高度差(平衡因子)不超过1。

3. 插入和删除操作的效率:
- 二叉树:在二叉树中插入和删除节点的效率取决于树的形状,可能较低。

- AVL树:由于AVL树要保持平衡,插入和删除节点时需要通过旋转操作来调整树的结构,因此插入和删除的效率可能较低。

4. 查找操作的效率:
- 二叉树:二叉树的查找操作时间复杂度为O(log n),其中n为节点数量。

- AVL树:由于AVL树的平衡特性,它的查找操作时间复杂度也为O(log n)。

5. 空间占用:
- 二叉树:二叉树的空间占用取决于树的形状,没有特定的要求。

- AVL树:由于AVL树需要维护平衡,它可能需要更多的额外空间。

总结:二叉树和AVL树都是树形结构,但AVL树具有自平衡特性。

相比之下,二叉树没有要求保持平衡,所以插入和删除的效率可能较低。

同时,AVL树的插入和删除操作需要通过旋转来实现平衡,因此它的效率可能较低。

但二叉树和AVL树的查找操作时间复杂度都为O(log n),并且都可以用于不同的应用场景。

avl方案介绍

avl方案介绍

avl方案1. 引言AVL树是一种自平衡二叉查找树,它在操作过程中保持树的高度平衡,从而保证了各种基本操作的时间复杂度为O(log n)。

本文将介绍AVL树的原理、实现方法以及应用场景。

2. AVL树的原理AVL树是由G.M. Adelson-Velsky和E.M. Landis在1962年提出的,它的名称取自于他们的名字的首字母。

AVL树的特点是每个节点的左子树和右子树的高度差不超过1,即保证了树的高度平衡。

AVL树的插入和删除操作会导致树的失衡,为了维持树的平衡,AVL树使用了旋转操作。

旋转操作主要包括左旋和右旋,通过重新调整子树的结构来使得树重新达到平衡。

3. 实现AVL树实现AVL树可以采用递归或迭代的方式,这里以递归方式为例进行说明。

3.1 AVL树节点定义首先需要定义AVL树的节点结构,一个简单的AVL树节点可以包括以下几个字段:class AVLNode:def__init__(self, key):self.key = keyself.left =Noneself.right =Noneself.height =1其中,key字段用于存储节点的键值,left和right字段分别指向节点的左子树和右子树,height字段表示节点的高度。

3.2 AVL树的插入操作AVL树的插入操作分为以下几个步骤:1.找到插入位置,若树为空,则直接插入新节点。

2.根据插入节点的键值与当前节点的键值进行比较,决定向左子树或右子树递归插入。

行旋转操作。

4.若当前节点失衡,根据失衡情况选择合适的旋转操作进行平衡调整。

下面是插入操作的递归实现代码:def insert(root, key):if not root:return AVLNode(key)elif key < root.key:root.left = insert(root.left, key)else:root.right = insert(root.right, key)root.height =1+ max(get_height(root.left), get_height(root.right)) balance = get_balance(root)# 左旋if balance >1and key < root.left.key:return rotate_right(root)# 右旋if balance <-1and key > root.right.key:return rotate_left(root)# 左右旋if balance >1and key > root.left.key:root.left = rotate_left(root.left)return rotate_right(root)# 右左旋if balance <-1and key < root.right.key:root.right = rotate_right(root.right)return rotate_left(root)return root3.3 AVL树的删除操作AVL树的删除操作也需要进行树的平衡调整,它分为以下几个步骤:1.找到待删除的节点。

课题_一步一步写平衡二叉树(AVL树)

课题_一步一步写平衡二叉树(AVL树)

一步一步写平衡二叉树(AVL树)平衡二叉树(Balanced Binary Tree)是二叉查找树的一个进化体,也是第一个引入平衡概念的二叉树。

1962年,G.M. Adelson-Velsky 和 E.M. Landis发明了这棵树,所以它又叫AVL树。

平衡二叉树要求对于每一个节点来说,它的左右子树的高度之差不能超过1,如果插入或者删除一个节点使得高度之差大于1,就要进行节点之间的旋转,将二叉树重新维持在一个平衡状态。

这个方案很好的解决了二叉查找树退化成链表的问题,把插入、查找、删除的时间复杂度最好情况和最坏情况都维持在O(logN)。

但是频繁旋转会使插入和删除牺牲掉O(logN)左右的时间,不过相对二叉查找树来说,时间上稳定了很多。

平衡二叉树实现的大部分过程和二叉查找树是一样的(学平衡二叉树之前一定要会二叉查找树),区别就在于插入和删除之后要写一个旋转算法去维持平衡,维持平衡需要借助一个节点高度的属性。

我参考了机械工业出版社的《数据结构与算法分析- C语言描述》写了一个C++版的代码。

这本书的AVLTree讲的很好,不过没有很完整的去描述。

我会一步一步的讲解如何写平衡二叉树,重点是平衡二叉树的核心部分,也就是旋转算法。

第一步:节点信息相对于二叉查找树的节点来说,我们需要用一个属性表示二叉树的高度,目的是维护插入和删除过程中的旋转算法。

代码如下://AVL树节点信息template<class T>class TreeNode{public:TreeNode():lson(NULL),rson(NULL),freq(1),hgt(0){}T data;//值int hgt;//以此节点为根的树的高度unsigned int freq;//频率TreeNode* lson;//指向左儿子的地址TreeNode* rson;//指向右儿子的地址};第二步:平衡二叉树(AVL)类的声明声明中的旋转函数将在后边的步骤中详解。

常见基本数据结构——树,二叉树,二叉查找树,AVL树

常见基本数据结构——树,二叉树,二叉查找树,AVL树

常见基本数据结构——树,⼆叉树,⼆叉查找树,AVL树常见数据结构——树处理⼤量的数据时,链表的线性时间太慢了,不宜使⽤。

在树的数据结构中,其⼤部分的运⾏时间平均为O(logN)。

并且通过对树结构的修改,我们能够保证它的最坏情形下上述的时间界。

树的定义有很多种⽅式。

定义树的⾃然的⽅式是递归的⽅式。

⼀棵树是⼀些节点的集合,这个集合可以是空集,若⾮空集,则⼀棵树是由根节点r以及0个或多个⾮空⼦树T1,T2,T3,......,Tk组成,这些⼦树中每⼀棵的根都有来⾃根r的⼀条有向的边所连接。

从递归的定义中,我们发现⼀棵树是N个节点和N-1条边组成的,每⼀个节点都有⼀条边连接⽗节点,但是根节点除外。

具有相同⽗亲的节点为兄弟,类似的⽅法可以定义祖⽗和孙⼦的关系。

从节点n1到nk的路径定义为节点n1,n2,...,nk的⼀个序列,并且ni是ni+1的⽗亲。

这个路径的长是路径上的边数,即k-1。

每个节点到⾃⼰有⼀条长为0的路径。

⼀棵树从根到叶⼦节点恰好存在⼀条路径。

对于任意的节点ni,ni的深度为从根到ni的唯⼀路径长。

ni的⾼是从ni到⼀⽚叶⼦的最长路径的长。

因此,所有的树叶的⾼度都是0,⼀棵树的⾼等于它的根节点的⾼。

⼀棵树的深度总是等于它最深叶⼦的深度;该深度等于这棵树的⾼度。

树的实现实现树的⼀种⽅法可以是在每⼀个节点除数据外还要有⼀些指针,使得该节点的每⼀个⼉⼦都有⼀个指针指向它。

但是由于每个节点的⼉⼦树可以变化很⼤⽽且事先不知道,故在各个节点建⽴⼦节点的链接是不可⾏的,这样将会浪费⼤量的空间。

实际的做法很简单:将每个节点的所有⼉⼦都放在树节点的链表中。

下⾯是典型的声明:typedef struct TreeNode *PtrToNodestruct TreeNode{ ElementType Element; PtrToNode FirstChild; PtrToNode NextSibling}下⾯是⼉⼦兄弟表⽰法的图⽰:树的遍历及应⽤⼀个常见的使⽤是操作系统中的⽬录结构。

AVL树的平衡策略

AVL树的平衡策略

AVL树的平衡策略AVL树是一种自平衡二叉搜索树,通过保持树的左右子树的高度差在指定范围内来维持平衡。

在本文中,我们将介绍AVL树的平衡策略以及它的实现。

一、AVL树的介绍AVL树是一种二叉搜索树,它的每个节点都包含一个额外的平衡因子,即该节点的左子树和右子树的高度差。

平衡因子可以是 -1、0 或 1,当平衡因子的绝对值超过1时,树就不再平衡,需要通过旋转操作进行调整。

二、插入操作在AVL树中插入一个节点时,首先进行二叉搜索树的插入操作。

接着,从插入节点的父节点开始向上回溯,更新每个祖先节点的平衡因子。

如果某个祖先节点的平衡因子超过了1,即左子树高度大于右子树,或者小于-1,即右子树高度大于左子树,那么就需要进行相应的旋转操作来恢复平衡。

三、旋转操作AVL树的旋转操作包括左旋和右旋。

左旋是指将当前节点的右子树提升为新的根节点,当前节点成为新根节点的左子树。

右旋则是相反的操作,将当前节点的左子树提升为新的根节点,当前节点成为新根节点的右子树。

四、平衡调整在进行插入操作后,AVL树可能会失去平衡,而需要进行相应的平衡调整。

平衡调整可以通过不同类型的旋转操作来实现,包括左旋、右旋、左右旋和右左旋等。

1. 左旋:当插入节点导致某个祖先节点的平衡因子为2,并且插入节点在该祖先节点的左子树的左子树上时,进行左旋操作。

2. 右旋:当插入节点导致某个祖先节点的平衡因子为-2,并且插入节点在该祖先节点的右子树的右子树上时,进行右旋操作。

3. 左右旋:当插入节点导致某个祖先节点的平衡因子为2,并且插入节点在该祖先节点的左子树的右子树上时,先对插入节点的左子树进行一次右旋操作,然后对祖先节点进行左旋操作。

4. 右左旋:当插入节点导致某个祖先节点的平衡因子为-2,并且插入节点在该祖先节点的右子树的左子树上时,先对插入节点的右子树进行一次左旋操作,然后对祖先节点进行右旋操作。

五、删除操作在AVL树中删除一个节点时,首先进行二叉搜索树的删除操作。

AVL树插入操作InsertAVL的实现

AVL树插入操作InsertAVL的实现

AVL树插⼊操作InsertAVL的实现AVL树是⾮常重要的⼀种数据结构,这⾥实现了在AVL树中的插⼊操作,包括插⼊后整个树的⾃平衡。

这⾥有⼏点值得注意的地⽅:1).左旋L_Rotate与右旋R_Rotate操作:这两个操作传递进来的参数是以TreeNode*&的形式传递进来的,也就是说传递的是指针的引⽤,效果等价于传递⼆级指针如果不加⼊&,则在函数内部更改的是形参的指向,因为实际上函数调⽤时,如果不采⽤引⽤传递,则会构造⼀个与原T指向同⼀个地⽅的临时变量指针,在X_Rotate的内部也是对这个临时变量进⾏操作,等到返回后对原来的T⼀点影响都没有。

因此对于指针的操作,如果说需要在某个函数内更改这个指针的指向,则要么传递⼆级指针,要么传递指针的引⽤。

2).在LR型或RL型中:以LR型为例,要根据不平衡点的左⼦树的根的右孩⼦rd的bf值来确定T与lc的bf值,其中rd->bf会出现等于0的情况。

这种情况只会出现在rc才是新插⼊的节点,也就是说lc->right在原来未插⼊时是NULL,只有在这种情况下才会显现在rc->bf=0,树却增⾼的情况。

⼀点⼩⼩的总结:AVL树第⼀次接触感觉很复杂,转来转去,四个形状,其实思考清楚后整个思路还是很简单的:⾸先是LL型与RR型:这两种情况是最简单的,只需要简单的右旋/左旋即可.以LL型为例⼦:对T右旋后,实际上就是将T->left->right接到T的left上,并将T->left->right改为接上T。

RR型也是如此。

然后是LR型与RL型:这两种情况复杂的原因在于,仅仅是右旋/左旋,T的bf仍不会变化。

以LR型为例⼦:问题出现在右旋后将T->left->right接到T的left并不会改变T的bf。

但实际上LR型可以看做这样⼀个过程:先将他转换为LL型。

也就是说,如果把插⼊节点插⼊到T->left的左⼦树上,就转变为第⼀个问题了。

相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

左边为调整前得节点,我们可以看出k1的左右子树已不再满足AVL平衡 条件,调整后的为右图。 我们可以看出,解决办法是将z上移一层,并将x下移一层,由于在原树 中k2 > k1,所以k1成为k2的左子树,而y是大于k1的,所以成为k1的右 子树。 为了设计算法,我们这里来看一个更易理解的:插入的是节点“6”
1.3
插入操作
插入的核心思路是通过递归找到合适的位置,插入新结点,然后看新结
点是否平衡(平衡因子是否为2),如果不平衡的话,就分成三种大情 况以及两种小情况: 1. 在结点的左儿子(X < T->item) 在左儿子的左子树 (X < T->l-> item),“外边”,要 做单旋转。 在左儿子的右子树 (X > T->l-> item),“内部”,要 做双旋转。 2. 在结点的右儿子(X > T->item) 在右儿子的左子树(X < T->r-> item),“内部”,要 做双旋转。 在右儿子的右子树(X > T->r-> item),“外边”,要 做单旋转。 3. (X == T->item) ,对该节点的计数进行更新。 当进行了旋转之后,必定会有结点的“父结点”是需要更新的,例如: 2 / \ 1 4 / \ 3 5 \ 6 上图是调整前的,下图是调整后的: 4 / \ 2 5 / \ \ 1 3 6 可以看出,根结点2不平衡,是由于它的右儿子的右子树插入了新的结 点6造成的。因此,这属于“外边”的情况,要进行一次单旋转。于是 我们就把结点4调整上来作为根结点,再把结点2作为4的左儿子,最后 把结点2的右儿子修改为原来的结点4的左儿子。 实现代码: AVLTree Insert(Item X, AVLTree T ) { if( T == NULL ) { /* Create and return a one-node tree */
1.3.2
双旋转
情况2:对该结点的左儿子的右子树进行了一次插入。 这种情况是单旋转调整不回来的,如下图:
图(1) 左--右双旋转如下:
图(2) 这里我们将图(1)的Y子树看成如图(2),以k2为子树根节点的树, 我们将其子树分成比D低,这里我我先对k3的左子树进行一次情形四的
右旋转,然后在进行一次情形1的左旋转,详细步骤如下:(红色框里面 的即是要进行单旋转的) 实现代码: //情形2 AVLTree DoubleRotateWithLeft( PAVLNode k3 ) { /* Rotate between K1 and K2 */ k3->l = SingleRotateWithRight( k3->l ); /* Rotate between K3 and K2 */ return SingleRotateWithLeft(k3); } 情况3:对该结点的右儿子的左子树进行了一次插入。 右—左双旋转如下:
T = (PAVLNode)malloc( sizeof(AVLNode ) ); if( T == NULL ) perror("malloc failed"); else { T->item = X; T->h = 0; T->l = T->r = NULL; T->count = 1; } } else if(compare(&X,&T->item) == -1)//插入情况1 { T->l = Insert( X, T->l ); if( Height( T->l ) - Height( T->r ) == 2 ) if(compare(&X, &T->l->item ) == -1)//左边左子树 单旋转 T = SingleRotateWithLeft( T ); else T = DoubleRotateWithLeft( T );//左边右子树 } else if( compare(&X,&T->item) == 1 ) //插入情况2 { T->r = Insert( X, T->r ); if( Height( T->r ) - Height( T->l ) == 2 ) if(compare(&X , &T->r->item) == 1)//右边右子树 单旋转 T = SingleRotateWithRight( T ); else T = DoubleRotateWithRight( T );//右边左子树 } else//插入情况3 T->count++; /* Else X is in the tree already; we'll do nothing */ T->h = MAX( Height( T->l ), Height( T->r ) ) + 1; return T; }
k1->r = k2; k2->h = MAX( Height( k2->l ), Height( k2->r ) ) + 1; k1->h = MAX( Height( k1->l ), k2->h ) + 1; return k1; /* New root */ } 情况4:对该结点的右儿子的右子树进行了一次插入。
1.2
为什么要用AVL树?
有人也许要问:为什么要有AVL树呢?它有什么作用呢? 我们先来看看二叉搜索树吧(因为AVL树本质上是一棵二叉搜索树), 假设有这么一种极端的情况:二叉搜索树的结点为1、2、3、4、5,也 就是: 1 \ 2 \ 3 \ 4 \ 5
聪明的你是不是发现什么了呢?呵呵,显而易见——这棵二叉搜索树其 实等同于一个链表了,也就是说,它在查找上的优势已经全无了——在 这种情况下,查找一个结点的时间复杂度是O(N)! 好,那么假如是AVL树(别忘了AVL树还是二叉搜索树),则会是: 2 / \ 1 4 / \ 3 5 可以看出,AVL树的查找平均时间复杂度要比二叉搜索树低——它是 O(logN)。也就是说,在大量的随机数据中AVL树的表现要好得多。
我们先对k1的右子树进行一次左旋转(情形1,然后再对k1进行一次右 旋转(情形4)。 实现代码: //情形3 AVLTree DoubleRotateWithRight( PAVLNode k1 ) { /* Rotate between K3 and K2 */ k1->r = SingleRotateWithLeft( k1->r ); /* Rotate between K1 and K2 */ return SingleRotateWithRight( k1 ); }
算法设计:由于是情形1对该结点的右儿子的右子树进行了一次插入, 该节点为“4”,我们同第一种情形类似。 实现代码: //情形4 AVLTree SingleRotateWithRight(PAVLNode k1) {
PAVLNode k2; k2 = k1->r; k1->r = k2->l; k2->l = k1; k1->h = MAX( Height( k1->l ), Height( k1->r ) ) + 1; k2->h = MAX( Height( k2->r ), k1->h ) + 1; return k2; /* New root */ }
算法设计:由于是情形1对该结点的左儿子的左子树进行了一次插入, 该节点是“8”,首先我们不考虑其父节点的情况,因为我们创建节点是 递归创建的,可以不用考虑其父节点与其的连接,这在后面递归创建的 时候会说到,由于“8”的右孩子将不会发生变化,但是其左孩子设 为“7”的右孩子,将7的右孩子设为“8”及其子树,然后返回“7”节点的指 针。 实现代码: //情形1 AVLTree SingleRotateWithLeft(PAVLNode k2) { PAVLNode k1; k1 = k2->l; k2->l = k1->r;
1.3
旋转
假设有一个结点的平衡因子为2(在AVL树中,最大就是2,因为结点是 一个一个地插入到树中的,一旦出现不平衡的状态就会立即进行调整, 因此平衡因子最大不可能超过2),那么就需要进行调整。由于任意一 个结点最多只有两个儿子,所以当高度不平衡时,只可能是以下四种情 况造成的: 1. 对该结点的左儿子的左子树进行了一次插入。 2. 对该结点的左儿子的右子树进行了一次插入。 3. 对该结点的右儿子的左子树进行了一次插入。 4. 对该结点的右儿子的右子树进行了一次插入。 情况1和4是关于该点的镜像对称,同样,情况2和3也是一对镜像对称。 因此,理论上只有两种情况,当然了,从编程的角度来看还是四种情 况。 第一种情况是插入发生在“外边”的情况(即左-左的情况或右-右的情 况),该情况可以通过对树的一次单旋转来完成调整。第二种情况是插 入发生在“内部”的情况(即左-右的情况或右-左的情况),该情况要 通过稍微复杂些的念
AVL树的复杂程度真是比二叉搜索树高了整整一个数量级——它的原理 并不难弄懂,但要把它用代码实现出来还真的有点费脑筋。下面我们来 看看:
1.1
AVL树是什么?
AVL树本质上还是一棵二叉搜索树(因此读者可以看到我后面的代码是 继承自二叉搜索树的),它的特点是: 1. 本身首先是一棵二叉搜索树。 2. 带有平衡条件:每个结点的左右子树的高度之差的绝对值 (平衡因子)最多为1。 例如: 5 5 / \ / \ 2 6 2 6 / \ \ / \ 1 4 7 1 4 / / 3 3 上图中,左边的是AVL树,而右边的不是。因为左边的树的每个结点的 左右子树的高度之差的绝对值都最多为1,而右边的树由于结点6没有子 树,导致根结点5的平衡因子为2。
1.3.1
单旋转
相关文档
最新文档