第七章:查找
7.3 树表的查找
当表插入、删除操作频繁时,使用动态查找表,可以维护表的有序性。其中,表结构在查找过程中动态生成,给定key,若表中存在,则成功返回;否则,插入key。
7.3.1 二叉排序树
- 定义:二叉排序树(Binary Sort Tree)又称二叉搜索树、二叉查找树。非空二叉排序树应该满足以下条件:
(1)若其左子树非空,则左子树上所有结点的值均小于根结点的值
(2)若其右子树非空,则右子树上所有结点的值均大于等于根结点的值
(3)其左右子树本身又各是一棵二叉排序树
![二叉排序树示例]()
- 中序遍历二叉排序树递增有序序列
根45,左子树(左3——>根12——>右24——>37),右子树(左null——>根53——>右(左61(左空——>根61——>右90(左78——>根90——>右空))——>根100——>右空))
![中序遍历二叉排序树]()
-
查找
与根结点比较大小,若大于等于根结点,则在右子树;否则在左子树。递归查找,直到在树中查找到等于key的根结点,查找成功;若没有找到该值,返回空值,查找失败。
![二叉排序树的存储结构]()
【算法思想】
(1) 若二叉排序树为空,则查找失败,返回空指针。
(2) 若二叉排序树非空,将给定key与根结点的关键字T->data.key进行比较:
① 若key = T->data.key,则查找成功,返回根结点地址;
② 若key < T->data.key,则进一步査找左子树;
③ 若key > T->data.key,则进一步查找右子树。
![查找/代码]()
在树中查找关键字与给定key相等的结点,比较关键字次数=该结点所在层数(最多比较次数=树的深度) -
二叉排序树的平均查找长度:
含有n个结点的二叉排序树的平均查找长度ASL和树的形态有关。
![二叉排序树的平均查找长度]()
- 如何提高形态不均衡的二叉排序树的查找效率?
答:平衡化处理,尽量让二叉树的形状均匀。
- 插入
首先,比较根结点和即将插入的key的大小,插入key小于根结点的关键字,则到左子树去找,否则去右子树找;再跟左子树的根结点比较,插入key小于根结点的关键字,则到左子树去找,否则去右子树找...如此循环进行,直到要比较的根结点为空,即在该位置插入。
【算法归纳】
- 若二叉排序树为空,则插入结点作为根结点插入到空树中
- 否则,继续在其左、右子树上查找
1)树中已有,不再插入
2)树中没有,查找直至某个叶子结点的左子树或右子树为空为止,则插入结点应为该叶子结点的左孩子或右孩子
![插入]()
-
生成
从空树出发,经过一系列查找、插入操作,可以生成一棵二叉排序树。 那么,一个无序序列可以通过构造二叉排序树而变成一个有序序列。构造树的过程就是对无序序列进行排序的过程。
注:不同插入次序的序列生成不同形态的二叉排序树。 -
删除
从二叉排序树中删除一个结点,不能把以该结点为根的子树都删去,只能删掉该结点。要保证删除后的二叉树仍然是二叉排序树。
-
被删除的是叶子结点:直接删去该结点
![叶子结点]()
-
被删除的结点只有左子树 or 只有右子树,用其左子树 or 右子树替换
![只有左子树]()
-
被删除的结点包含左子树 and 右子树:一种是采用前驱替换,首先在左子树找到最大key的结点,将其作为左子树的双亲,同时删除该最大key的结点,修改其双亲的指针域为指向该node的孩子;另外一种是后继替换,首先在右子树找到最小key的结点,将其作为右子树的双亲,同时删除该最小key的结点,修改其双亲的指针域为指向该node的孩子。
![]()
因此,删除主要关注如何修改其双亲的指针域。删除之后的二叉排序树深度更小,查找效率更高,同时也让二叉树更平衡。
7.3.2 平衡二叉树
- 定义:平衡二叉树(balanced binary tree)又称AVL树(Adelson-Velskii and Landis),平衡二叉树一定是二叉排序树。一棵非空的平衡二又树是具有下列性质的二叉排序树
① 左子树与右子树的高度之差的绝对值小于等于1;
② 左子树和右子树也是平衡二叉排序树。
平衡因子(BF):平衡二叉树的左子树的高度 - 右子树的高度。由定义可知,BF取值{-1,0,1}。
- 判断平衡二叉树:
![判断平衡二叉树]()
对于一棵有n个结点的AVL树,其高度保持在\(O(log_{2}n)\)数量级,ASL(平均查找长度)也保持在\(O(log_{2}n)\)数量级。
- 失衡二叉排序树的调整
当我们在一个AVL树上插入一个结点后,有可能导致AVL树失衡,即出现平衡因子绝对值大于1的结点,如:2、-2.
![4种失衡]()
- 4种失衡调整方法 平衡旋转
插入一个结点,产生不止一个失衡结点,选择最小失衡子树(深度最小)的根结点作为失衡结点。
① LL型:插入在左子树的左子树上导致的失衡。\(\alpha\)和\(\beta\)是B左子树和右子树,h表示深度。
![LL型]()
![LL型]()
② LR型:插入在左子树的右子树上导致的失衡。


③ RL型:插入在右子树的左子树上导致的失衡。


④ RR型:插入在右子树的右子树上导致的失衡。


- 调整原则:1)降低高度 2)保持二叉排序树性质。LL型中顺时针把A拽下来(C<B<A),LR型把C拽上去(B<C<A),RL型把C拽上去(A<C<B),RR型中逆时针把A拽下来(A<B<C)。规律就是,最小的key结点在左子树,最大的key结点在右子树,中间key的结点上升。
![调整原则]()
- 构建一个平衡二叉树
根据输入关键字序列,构建二叉排序树;如果有失衡,则进行调整。再根据调整后的二叉树进行插入。这里每一步都要计算结点的平衡因子。
7.3.3 红黑树
B-树
B+树
键树
7.4 哈希表(散列表)的查找
7.4.1 基本定义
- 基本思想:记录的存储位置与关键字之间存在对应关系(Hash函数)求的是存储位置
$Loc(i)=H(keyi)$
根据keyi关键字查Hash表中的值Loc(i),该值为keyi存储的位置。若查不到则返回一个特殊值(空指针或空记录)
优点:查找效率高
缺点:空间效率低 e.g H(key)=k
-
散列方法:选取某个函数H(key),根据该函数输入key计算元素的存储位置,并按此存放。查找时,比较H(key)的关键码 与给定值k是否相等,来确定查找是否成功。其中,H(key)=k称为散列函数。根据上述思想构建的表称为散列表。
-
冲突:不同的关键码映射到同一个散列地址。
H(k)=k mod 7(关键字除以7取余,该余数为存储地址)
![冲突]()
- 同义词:具有相同函数值的多个关键字。如图示的39、25和11。
在散列查找方法中,冲突是不可避免的,只能尽可能减少。
7.4.2 散列函数的构造方法
-
使用散列表要解决好两个问题,1)构造好的散列函数:(a)所选函数尽可能简单,以便提高转换速度;
(b)所选函数对关键码计算出的地址,应在散列地址集中致均匀分布,以减少空间浪费。2)制定一个好的解决冲突的方案:查找时,如果从散列函数计算出的地址中查不到关键码,则应当依据解决冲突的规则,有规律地查询其它相关单元。 -
构造散列函数考虑的因素:
①执行速度(即计算散列函数所需时间);
②关键字的长度;
③散列表的大小(希望散列的地址空间尽量少)
④关键字的分布情况(希望存放元素尽量均匀,避免冲突);
⑤查找频率。
常用的构造方法有:直接定址法、数字分析法、平方取中法、折叠法、除留余数法、随机数法
- 直接定址法:
![直接定址法]()
- 除留余数法:更加常用(比其他散列函数好)
![除留余数法]()
7.4.3 处理散列地址冲突的方法
处理冲突的方法:开放定址法(开地址法)、链地址法(拉链法)、再散列法(双散列函数法)、建立一个公共溢出区。
- 开放定址法:
【基本思想】有冲突时就去寻找下一个空的散列地址,只要散列表足够大空的散列地址总能找到,并将数据元素存入。\(d_{i}\)为增量序列,定义增量序列有几种常用方法:线性探测法、二次探测法、伪随机探测法

一个线性探测法例子:散列表的长度为11。按照顺序存储输入序列的关键码,当遇到冲突时,采用线性探测法构造\(H_{1}\),其中\(d_{i}\)取1,存储位置往后移一位,如果该位置为空,则在此位置存储关键码;否则继续后移(使用更新的\(H_{i}\)),直到找到空位置。(先到先得,先安排最前的关键码)

平均查找长度ASL:

一个二次探测法例子:基于\(H_{1}\)找到的散列地址仍然冲突,则继续尝试\(H_{2}\)寻找新的散列地址...直到找到空的散列地址来存储关键码。

- 链地址法:比开放地址法要好
【基本思想】相同散列地址的记录,将其链成一单链表。m个散列地址就设m个单链表,然后用一个数组将m个单链表的表头指针存储起来,形成一个动态的结构。
![链地址法]()
具体实现步骤:
① 取数据元素的关键字key,计算其散列函数值(地址)。若该地址对应的链表为空,则将该元素插入此链表;否则,执行②解决冲突。
② 根据选择的冲突处理方法,计算关键字key的下一个存储地址。若该地址对应的链表不为空,则利用链表的前插法或后插法将钙该元素插入此链表。
优点:1)非同义词(由于探测导致的,原同义词向非同义词位置移动,而产生冲突)不会冲突,无“聚集”现象;2)链表上结点空间动态申请,更适合于表长不确定的情况。
7.4.4 散列表的查找
-
和处理冲突的思路一致:
![散列表的查找]()
-
散列表的查找效率分析:ASL与装填因子α有关。
![查找效率分析]()
![ASL与装填因子α有关]()






















浙公网安备 33010602011771号