第十一章      执行查询算法

基本概念:

         三类查找方法:线性查找、树形查找、哈希表查找

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

         静态查找表:与动态查找表相反

         查找过程中对关键字需要执行的平均比较次数(也称平均比较长度作为衡量一个查找算法优劣的标准

         平均比较长度:

wKioL1QqezeyrJAyAAAfi-VGEyI734.jpg

         其中:n是结点的个数;pi是查找第i个结点的概率。若不特别申明,认为每个结点的查找概率相等,都为1/nci是找到第i个结点所需进行的比较次数。

线性查找:

         基本思想:从表的一端开始,顺序扫描线性表,依次将扫描的结点关键字和给定K值相比较。若当前扫描到的结点关键字与K相等,则查找成功;若扫描结束,仍未找到关键字等于K的结点,则查找失败。

         算法的平均查找长度为:n

         在下列两种情况下,只能采用顺序查找:

1)  如果顺序表为无序表,则只能用顺序查找

2)  采用链式存储结构的线性表,只能采用顺序查找

二分查找

         二分查找又称折半查找,它是一种效率较高的查找方法。二分查找要求线性表示有序表,即表中结点按关键字有序,并且要用顺序表作为表的存储结构。

         基本思想:设置三个变量lowhighmid,它们分别指向表的当前指向表的当前待查找范围的下界,上界和中间位置。初始时,low=0high=n-1,设待查找数据元素的关键字为Key

1)  mid=low+high/2

2)  比较KeyR[mid]Key值的大小,若:

  • R[mid]Key值等于Key则查找成功,结束查找

  • R[mid]Key值小于Key,表明关键字为Key的记录可能位于记录R[mid]的右边,修改查找范围,令下界指示变量low=mid+1,上界指示变量hight保持不变

  • R[mid]Key值大于Key,表明关键字为Key的记录可能位于记录R[mid]的左边,修改查找范围,令下界指示变量high=mid-1,下界指示变量low保持不变

  • 比较当前变量lowhigh的值,若lowhigh,重复(1)、(2),若low>high,表明整个查找完毕,线性表中不存在关键字为Key的记录,查找失败。

平均查找长度:ASL=log2n+1-1

分块查找:

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

基本思想:分块查找要求把顺序表分成若干块,每一块的键值存储顺序是任意的,但要求“分块有序”,前一块中的最大键值小于后一块中的键值。即块间结点有序,块内结点任意。另外,还需要简历一个索引表,索引表中的每一项对应顺序表的一块,索引项由关键字域好链域组成,关键字域存放对应块内结点的最大值,链域存放对应块首结点的位置。索引表中的索引项是按键值递增顺序存放。

抽取各块中的最大关键字及其起始位置构成一个索引表,索引表按关键字有序,所以索引表是一个递增有序集。

在带索引表的顺序表中查找关键字等于Key的记录时,需要分两步进行

1)             首先查找索引表,确定待查记录所在块。索引表示有序表,可以此采用二分查找或顺序查找,以确定待查找的结点在哪一块。

2)             在已确定的块中进行顺序查找。当块内的记录是任意排列的,只能用顺序查找。

平均查找长度:ASL=spacer.gif,分块查找是一种介于顺序查找和二分查找之间的查找方法,它的速度要比顺序查找速度快,但付出的代价增加辅助存储空间和将顺序表分块排序;同时它的速度要比二分查找法速度慢,但好处是不需要对全部记录进行排序。

哈希查询技术

         基本原理:将给定的键值转换为偏移地址来检索记录

         键转换为地址是通过一种关系(公式)来完成的,这就是哈希(散列)函数。哈希函数对键执行操作,从而给定一个哈希值,该值是代表可以找到该记录的位置。

         哈希法的基本思想是:设置一个长度为m的表T,用一个函数将数据集合中n个记录的关键字尽可能唯一地转换成0~m-1范围内的数值。

         哈希表的冲突现象:两个不同的关键字,由于哈希函数值相同,因而被映射到同一表位置上。该现象称为冲突或碰撞。发生冲突的两个关键字称为该哈希函数的同义词。

构造哈希函数和简历解决冲突的方法是建立哈希表的两大任务。

好的哈希函数选择有两条标准:

1)  简单并且能够快速计算

2)  能够在址空间中获取键的均匀分布

几种常用的构造哈希函数的方法:

  1. 平均取中法:具体的做法是先通过关键字的平方值扩大相近数的差别,然后根据表的长度取中间的几位数作为哈希的函数值。又因为一个乘积的中间几位和乘数的每一位都相关,所以由此产生的散列地址较为均匀。

  2. 除余法:以表长m来除关键字,取其余数作为散列地址。

  3. 折叠移位法:根据哈希表长将关键字尽可能分成若干段,然后将这几段的值相加,并将最高位的进位舍去,所得结果即为其哈希地址。相加有两种方法,一种是顺折,即把每段中的各位值对齐相加,称之为移位法;另一种对折,像纸条一样,把原来关键字按照划分的中界向中间折叠,然后求和,称之为折叠法。

解决哈希冲突

  1. 开放定址法:当冲突发生时,按照某种方法探测表中的其他存储单元,直到找到空位置为止。下面介绍几种

1)  线性探测法:将散列表T[0m]看成是一个循环向量,若初始探测的地址为dhkey=d),则最长的探测序列为:

dd+1d+2,…,m-101,…,d-1

即:探测时从地址d开始,首先探测T[d],然后依次探测T[d+1]…直到,T[m-1],此后又循环到T[0]T[1],…,直到T[d-1]为止。

探测过程终止于三种情况:

  • 若当前探查的单元为空,则表示查找失败(若是插入则将Key写入其中)

  • 若当前探查的单元中还有Key,则查找成功,但对于插入意味着失败

  • 若探测到T[d-1]是仍未发现空单元也未找到key,则无论是查找还是插入均意味着失败(此时表满)

2)  二次探查法:二次探查法的探查序列为:

hi=hkey+i*i%m      0im-1

即探查序列为d=hkey),d+12d+22,…等。

   该方法的缺陷是不易探查到整个散列空间。

3)  双重哈希法

该方法是开放定址法中最好的方法之一。在该方法中,一旦发生冲突,会应用第二个哈希函数以获取备用位置。第一次试探有冲突的键很可能在第二个哈希函数结果中有不同的值。

  1. .链表法:链表法解决冲突中的做法是:将所有关键字为同义词的结点连接在同一个单链表中,若选定的哈希表长度为m,则可将哈希表定义为一个由m个头指针组成的指针数组T[0m-1]。凡是散列地址为i的结点均插入到以T[i]为头指针的单链表中。T中各分量的初值均为空指针。在链表法中,装填因子α可以大于1,但一般取α≤1