数据结构 查找-详细介绍

第一节 基本概念

1.查找

查找的定义是:给定一个值K,在含有n个结点的表中找出关键字等于给定值K的结点。若找到,则查找成功,返回该结点的信息或该结点在表中的位置; 否则查找失败,返回相关的指示信息。

2.查找表的数据结构表示

(1)动态查找表和静态查找表
若在查找的同时对表做修改操作(如插入和删除),则相应的表称之为动态查找表。否则称之为静态查找表。

(2)内查找和外查找
若整个查找过程都在内存进行,则称之为内查找;反之,若查找过程中需要访问外存,则称之为外查找。

3、平均查找长度ASL

查找运算的主要操作时关键字的比较,所以通常把查找过程中对关键字需要执行的平均比较次数(也称为平均查找长度)作为衡量一个查找算法效率优劣的标准。

平均查找长度ASL(Average Search Length )定义为:

在这里插入图片描述
其中:

a.n是结点的个数;
b.Ci是找到第i个结点所需进行的比较次数
c.Pi是查找第i个结点的概率。若不特别声明,认为每个结点的查找概率相等,即:
在这里插入图片描述

第二节 顺序表的查找

顺序表是指线性表的顺序存储结构,具体数据类型定义:

在这里插入图片描述

一,顺序查找

1.一般顺序表的查找算法

(1)算法描述

在这里插入图片描述

(2)算法分析

a.查找成功的情况:最好的情况比较1次,最坏的情况比较n次
查找成功时的平均查找长度=(1+2+…+n)/n=(n+1)/2

b.查找失败时的查找长度=(n+1)

c.如果查找成功和不成功机会相等,顺序查找的平均查找长度为
((n+1)/2+(n+1))/2 =3/4(n+1)

2.在递增有序的顺序表的查找算法

(1)算法描述

在这里插入图片描述

(2)算法分析

a.查找成功的平均查找长度=(n+1)/2

b.查找失败的平均查找长度=(n+1)/2

c.如果查找成功和不成功机会相等,该算法的平均查找长度为((n+1)/2+(n+1)/2)*1/2 = (n+1)/2

二、二分查找法(重点)

对有序表可以用查找效率较高的二分查找方法来实现查找运算。

1、二分查找法的思想

二分查找的思想:首先将待查的k值和有序表R[1…n]的中间位置mid上的记录的关键字进行比较,若相等,则查找成功,返回该记录的下标mid;否则,若R[mid].key>k,则k在左字表R[1…mid-1]中,接着再在左子表中进行二分查找即可;否则,若[min].key<k,则说明待查记录在右子表R[mid+1…n]中,接着只要在右子表中进行二分查找即可。这样,经过一次关键字的比较,就可以缩小一半的查找空间,如此进行下去,直到找到关键字为k的记录或者当前查找区间为空时(即查找失败)为止。二分查找的过程是递归的。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3.算法描述

(1)二分查找递归算法

在这里插入图片描述

(2)二分查找非递归算法

在这里插入图片描述
4.算法分析

二分查找方法可以用一颗判定树描述,查找任一元素的过程对应该树中从根节点到相应结点的一条路径。最短的查找长度为1,最长的查找长度为对应判定树的深度log2n+1向下取整,平均查找长度(n+1)/n*log2(n+1)-1 =log(n+1)-1.二分查找方法效率高是有代价的,因为有序表是通过排序而得到的,而排序操作又是比较费时的,二分查找只适用于顺序结构上的有序表,对链式结构无法进行二分查找。

在这里插入图片描述

5.应用实例

在这里插入图片描述
三,索引顺序查找

索引顺序查找又称分块查找,它是一种性能介于顺序查找和二分查找之间的查找方法。

1.索引查找表的存储结构

(1)分块有序的线性表

表R[1…n]均分为b块,前b-1块中结点个数为S=[n/b] ,第b块的结点数小于等于s;每一块中的关键字不一定有序,但前一块中的最大关键字必须小于后一块中的最小关键字,即表是‘分块有序’的。

(2)索引表

抽取各块中的最大关键字及其起始位置构成一个索引表ID [ 1 …b ] , 即 :ID [ i ] (1<=i<=b)中存放第i块最大关键字及该块在表R中的起始位置。由于表R是分块有序的,所以索引表是一个递增有序表。

【例】下图就是满足上述要求的存储结构,其中R只有18个结点,被分成3块,每块中有6个结点,第一块中最大关键字21小于第二块中最小关键字23,第二块中最大关键字45小于第三块中最小关键字48.

在这里插入图片描述
2、索引查找的基本思想

(1)首先查找索引表
索引表是有序表,可采用二分查找或顺序查找,以确定待查的结点在那一块。

(2)然后在已确定的块中进行顺序查找
由于块内无序,只能用顺序查找。

3.索引查找的平均查找长度

(1)查找索引表采用二分查找时的平均查找长度。

ASLblk = log2(b+1) -1+(s+1)/2 = log2(n/s +1)+s/2

(2)查找索引表采用顺序查找时的平均查找长度
ASLblk = (b+1)/2 +(s+1)/2 =(b+s)/2 +1= (n/s+s)/2+1 =(块数+块长)/2+1

当s取根号n(即s=b)时,ASLblk达到最小值根号n+1,即当采用顺序查找确定块时,应将各块中的结点数选定为根号n。

四,三种查找方法比较

1、顺序查找

优点:算法简单,对表的存储结构无任何要求。
缺点:查找效率低,查找成功的平均查找长度为(n+1)/2。查找失败的查找长度为(n+1).

2.二分查找

优点:二分查找的速度,效率高,查找成功的平均查找长度约为log(n+1)-1。

缺点:要求表以顺序存储表示并且是按关键字有序,使用高效率的排序方法也要花费O(nlog2n)的时间。另外,当对表结点进行插入或删除时,需要移动大量的元素,所以二分查找使用于表不易变动且又经常查找的情况。

3.分块查找
优点:在表中插入或删除一个记录时,只要找到该记录所属的块,就可以在该块内进行插入或删除运算。因为块内记录是无序的,所以插入或删除比较容易,无需移动大量记录。

缺点:是需要增加一个辅助数组的存储空间和将初始表块排序的运算,它也不适宜用链式存储结构。

此外,顺序查找,二分查找和分块查找三种查找算法的时间复杂度分别为:O(n),O(log2n)和O()。分块查找算法的效率介于顺序查找和二分查找之间。

【例】若表中有10000个结点,则应把它分成100个块,每块中含100个结点,用顺序查找确定块,分块查找平均需要做根号n+1=根号10000+1=101次比较;顺序查找平均需要做(n+1)/2=5000次比较;二分查找最多需log2 10000 +1=14次比较,平均查 找 长度 log2 10001-1。

第三节 树表的查找(一)

一、二叉排序树

1.二叉排序树的概念

(1)二叉排序树的定义
二叉排序树(Binary Sort Tree,BST)又称二叉查找,是一种特殊的二叉树,二叉排序树或者是空树,或者是满足如下性质的二叉树;

a.若它的左子树非空,则左子树上所有结点的值均小于根结点的值;

b.若它的右子树非空,则右子树上所有结点的值均大于根结点的值;

c.左/右子树本身又是一颗二叉排序树。

在这里插入图片描述

(2)二叉排序树的重要性质

中跟遍历一颗二叉排序树所得的结点访问序列是按简直的递增序列。

(3)二叉排序树的数据类型定义

在这里插入图片描述
2、二叉排序树的插入

(1)算法思想

在二叉排序树中插入新结点,要保证插入后仍满足BST性质。其插入过程是:

a.若二叉排序树T为空,则为待插入的关键字key申请一个新结点,并令其为根;

b.若二叉排序树T不为空,则将key和根的关键字比较;

c. 若二者相等,则说明是树中已有此关键字key,无须插入。

若key<t–key,则 将key插入根的左子树中。
若key>t–key,则将它插入根的右子树中。

子树中的插入过程与上述的树中插入过程相同。如此进行下去,直到将key作为一个新的叶结点的关键字插入到二叉排序树中,或者直到发现树中已有此关键字为止。

(2)实例分析
【例】写出把无序序列(20,10,30,15,25,5,35,12,27)建成二叉排序树的过程。
【解答】采用逐点插入结点的方法即可建立相应的二叉排序树。建成二叉排序树的过程如图所示
在这里插入图片描述
在这里插入图片描述

3.二叉排序树的生成

(1)算法思想

从空的二叉树开始,每输入一个结点数据,生成一个新结点,就调用一次插入算法将它插入到当前生成的二叉排序树中

(2)算法描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
4.二叉排序树的查找

(1)算法思想

若二叉排序树为空,则表明查找失败,应返回空指针。否则,若给定值key等于根结点的关键字,则表明查找成功,返回当前根结点指针;若给定值key小于根结点的关键字,则继续在根结点的左子树中查找,若给定值key大于根结点的关键字,则继续在根结点的右子树中查找。显然,这是一个递归的查找过程。

(2)算法描述
在这里插入图片描述
(3)算法分析

二叉排序树上的查找长度与二叉排序树的形态有关,若二叉排序树是一棵理想的平衡树(是指树中任一结点的左右子树的高度差不能大于1),则进行查找的时间复杂度为O(log2n);若退化为一棵单支树,则其查找的时间复杂度为O(n).对于一般情况,其时间复杂度应为O(log2n).

【例】给定表(20,15,18,12,25,27,30,22,17,20,28),按数据元素在表中的次序构造一棵二叉排序树,求出其平均查找长度。

在这里插入图片描述

5.二叉排序树上的删除

从BST树上删除一个结点,仍然要保证删除后满足BST的性质。设被删除结点为p,其父结点为f,如图(a)所示的BST树。具体删除情况分析如下:

在这里插入图片描述
(1)若p是叶子结点:直接删除p,如图(b)所示。

(2)若p只有一颗子树(左子树或右子树),直接用p的左子树(或右子树)取代p的位置而成为f的一棵子树。即原来p是f的左子树,则p的子树成为f的左子树;原来p是f的右子树,则p的子树成为f的右子树,如图(c)所示。

(3)若p既有左子树又有右子树,处理方法有以下两种,可以任选其中一种。

a.用p的直接前驱结点(中序遍历)代替p,即从p的左子树中选择值最大的结点s放在p的位置(用结点s的内容替换结点p内容),然后删除结点s.s是p的左子树中最右边的结点且没有右子树,如图(d)所示。

b.用p的直接后继结点(中序遍历)代替p,即从p的右子树中选择值最小的结点s放在p的位置(用结点s的内容替换结点p的内容),然后删除结点s。s是p的右子树中的最左边的结点且没有左子树。例如,对图(a)所示的二叉排序树,删除结点8后所得的结果如图(e)所示。

在这里插入图片描述

第三节 树表的查找(二)

二,B树

1.B树的概念

(1)B树的定义
一棵m(m>=3)阶的B树,或为空树,或为满足下列性质的m叉树:

a.每个结点至少包含下列信息域:
(n,p0,k1,p1,k2…,kn,pn)

其中,n为关键字的个数:

ki(1<=i<=n)为关键字,且ki<ki+1(1<=i<=n-1);
pi(1<=i<=n)为指向子树跟结点的指针,且pi所指向子树中所有结点的关键字均小于ki+1,pn所指子树中所有结点关键字均大于kn.

b.树中每个结点至多有m棵子树。
c.若树为非空,则根结点至少有1个关键字,至多有m-1个关键字。因此,若跟结点不是叶子,则它至少有两棵子树。
d.所有的叶结点都在同一层上,并且不带信息(可以看做是外部结点或查找失败的结点,实际上这些结点不存在,指向他们的指针均为空),叶子的层数为树的高度h。
f.每个非根结点中包含的关键字个数满足:[m/2]-1<=n<=m-1. 因为每个内部结点的度数正好是关键字总数加1,所以,除根结点之外的所有非终端结点(非叶子结点的最下层的结点称为终端结点)至少有[m/2]棵子树,至多有m棵子树。

(2)实例
在这里插入图片描述
(3)B树的结点类型定义

在这里插入图片描述
2.B树上的插入

在B树中插入一个结点的过程:先在最低层的某个非终端结点中添加一个关键字。若该结点中关键字的个数不超过m-1,则插入完成,否则要产生结点“分裂”。“分裂”结点时把结点分成两个,将中间的一个关键字拿出来插入到该结点的双亲结点上,如果双亲结点中已有m-1个关键字,则插入后将引起双亲结点的分裂,这一过程可能波及B树的根结点,引起根结点的分裂,从而使B树长高一层。

在这里插入图片描述
在这里插入图片描述
3.B树上的删除

(1)若需要删除关键字所在结点中的关键字数目不小于m/2向上取整,则只需要该结点中关键字和相对于的指针删除。

在这里插入图片描述

(2)若需删除关键字所咋结点中的关键字数目等于m/2-1向上取整,即关键字数目已是最小值,直接删除该关键字会破坏B树的性质。删除这样关键字分两种情况处理:

a.若删除结点的左(或右)邻兄弟结点中的关键字数目不小于m/2向上取整,则将其兄弟结点中的最大(或最小)的关键字上移至双亲结点中,而将双亲结点中相应的关键字移至删除关键字所在结点中。

在这里插入图片描述
b.若需删除关键字所在结点及其相邻的左,右兄弟(或只有一个兄弟)结点中关键字数目均等于m/2-1向上取整,则按上述情况a的移动操作就不能实现。此时,就需要将被删除结点与其左兄弟或右兄弟结点进行“合并”。

在这里插入图片描述
上述情况b如果因“合并”操作引起对父结点中关键字的删除,又可能要合并结点,这一过程可能波及根,引起对根结点中关键字的删除,从而可能使B树的高度降低一层。

在这里插入图片描述
4.B树上的查找

(1)查找算法思想

在B树中查找一个关键字等于给定值K的具体过程:若B树为非空,则首先取出根结点,将给定值K依次与关键字向量中从高下标端(key[keynum])开始的每个关键字进行比较,直到K>=Ki(0<=i<=n=keynum,用key[0]作为中止标志,存放给定的查找值K)为止,此时,若K=Ki且i>0,则表明查找成功。返回具有该关键字的结点的存储位置及K在key[1…keynum]中的位置;否则,其值为K的关键字只可能落在当前结点的pi所指向的子树上,接着只要在该子树商继续进行查找即可。这样,每取出一个结点比较后就下移一层,直到查找成功,或被查找的子树为空(即查找失败)为止。

在这里插入图片描述
在这里插入图片描述

先和根结点a比较:把K=18赋给k0.k=18小于k1的值48,再同a结点中k0比较,k0=k,因为i=0,所以接着取出a结点的p0指向的结点b,用K与b结点中的k2=32进行比较,k=18<k2=32
而K=18>k1=16,所以再取出b结点的p1所指向的结点e;因为k=k1,因此查找成功,返回e结点的存储地址以及k1d的位置pos=1.

三、B+树

B+树是一种常用语文件组织的B树的变形树。一棵m阶的B+树和m阶的B树的差异在于:

(1)有k个孩子的结点必含有k个关键字。
(2)所有的叶结点中包含了关键字的信息及指向相应结点的指针,且叶子结点本身依照关键字的大小从小到大顺序链接。
(3)所有非终端结点可看成是索引部分,结点中仅含有其子树(根结点)中的最大关键字(或最小)关键字。

下图所示是一棵3阶的B+树。通常在B+树上上有两个头指针root和sqt,前者指向跟结点,后者指向关键字最小的叶子结点。因此,可以对B+树进行两种查找运算:一种是从最小关键字起进行顺序查找,另一种是从根结点开始进行随机查找。

在这里插入图片描述

第四节 散列表查找

一、散列表的概念
1.散列的概念

“散列”即时一种存储方式,又是一种查找方法。这种查找方法称为散列查找。散列的基本思想是通过由散列函数决定的键值与散列地址之间的对应关系来实现存储组织和查找运算。

2.实例分析
【例】有个线性表A=(31,62,74,36,49,77),散列函数为H(key)=key%m即用元素的关键字key整除m,取其余数作为存储该元素的散列地址,m一般取小于或等于散列表长的最大素数,在这里取m=11,表长业为11,因此可以得到每个元素的散列地址:

在这里插入图片描述

二,散列函数的构造方法

1、直接地址法
直接地址法是以关键字key本身或关键字加上某个常量C作为散列地址的方法。对应的散列函数H(key)为:H(key)=key +C
特点:方法计算简单,并且没有冲突。它适合于关键字的分布基本连续的情况,若关键字分布不连续,空号较多,将会造成较大的空间浪费。

2,数字分析法
数字分析法是假设有一组关键字,每个关键字由n位数组成,数字分析法是从中提取数字分布比较均匀的若干位作为散列地址。

3.除余数法

除余数法是一种最简单也最常用的一种散列函数构造方法。散列函数:H(k)=k%p.
其中,p最好选取小于或等于表长m的最大素数。

4.平方取中法
平方取中法是取关键字平方的中间几位作为散列地址的方法

5.折叠法
折叠法是首先把关键字分割成位数相同的几段(最后一段的位数可少一些),段的位数取决于散列地址的位数,由实际情况而定,然后将他们的叠加和(舍去最高进位)作为散列地址的方法。

【例】关键字k=98 123 658 ,散列地址为3位,则将关键字从左到右每三位一段进行划分,得到的三个段为981、236和58,叠加后值为1275,取低3位275作为关键字98 123 658的元素的散列地址

三,处理冲突的方法

1、开放定址法
开放定址法的思想:使用某种方法在散列表中形成一个探查序列,沿着此序列逐个单元进行查找,直到找到一个空闲的单元时将新的结点存入其中。

开放定址法又分为线性探查法、二次探查法和双重散列法。

(1)线性探查法
探查序列可以由下述公式得到:di=(d+i)%m
其中:di表示第i次探查的地址,m表示散列表的长度。

【例】设散列函数为h(key)=key%11;散列地址表空间为0-10,对关键字序列{27,13,55,32,18,49,24,38,43},利用线性探测法解决冲突,构造散列表。并计算查找成功时的平均查找长度。
在这里插入图片描述
(2)二次探查法

在这里插入图片描述

(3)双重散列法

在这里插入图片描述
2.拉链法(链地址法)

用拉链法处理冲突的办法是:把具有相同散列地址的关键字(同义词)值放在同一个单链表中,称为同义词链表。

在这里插入图片描述
四.散列表的查找

1.线性探查法解决冲突的查找和插入算法

在这里插入图片描述
(1)采用线性探查法的散列表查找算法

在这里插入图片描述
(2)在散列表上插入一个结点的算法

在这里插入图片描述
2.拉链法建立散列表上的查找和插入运算

采用拉链法的散列表类定义:

在这里插入图片描述

(2)插入算法

在这里插入图片描述

3.几种处理冲突方法的散列表的平均查找长度比较
【例】设散列函数h(k)=k%13,散列表地质空间0-12,对给定的关键字序列(19,14,01,68,20,84,27,26,50,36)分别以拉链法和线性探查法解决冲突构造散列表,画出所构造的散列表,指出在这两个散列表中查找每一个关键字时进行比较的次数,并分析在等概率情况下查找成功和查找不成功的平均查找长度以及当结点数为n=10时的顺序查找和二分查找成功与不成功的情况.

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

**注意:**结点个数n,散列表长度为m,散列表的平均查找长度不是n的函数,而是装填因子α=n/m的函数,采用四种不同方法处理冲突时得出的散列表的平均查找长度:

在这里插入图片描述
开放定址法要求散列表的装填因子α<=1,实用中一般取0.65-0.9之间的某个值为宜。在拉链法中,其装填因子α可以大于1,但一般均取α<=1.

小结:

讨论了顺序表的查找,树表的查找以及散列查找。重点讨论了二分查找,二叉,排序树及散列表查找,这也是本章需要学习掌握的重点。不仅要理解这些查找算法的基本思想,还要能够写出各种算法记录的查找和插入顺序过程,以及分析比较计算这些算法在等概率情况下查找成功时的平均查找长度等。

  • 20
    点赞
  • 131
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值