收藏 分享(赏)

数据结构课件查找.ppt

上传人:精品资料 文档编号:11295383 上传时间:2020-03-13 格式:PPT 页数:93 大小:803KB
下载 相关 举报
数据结构课件查找.ppt_第1页
第1页 / 共93页
数据结构课件查找.ppt_第2页
第2页 / 共93页
数据结构课件查找.ppt_第3页
第3页 / 共93页
数据结构课件查找.ppt_第4页
第4页 / 共93页
数据结构课件查找.ppt_第5页
第5页 / 共93页
点击查看更多>>
资源描述

1、2020/3/13,1,第九章 查找,由于查找运算的使用效率很高,几乎在任意一个计算机系统软件和应用软件中都会涉及到,所以当问题所涉及的数据量相当大时,查找方法的效率就显得格外重要。在一些实事查询系统中尤其如此。因此,本章将系统地讨论各种查找方法,并通过对它们的效率分析来比较各种查找方法的优劣。,2020/3/13,2,第九章 查找,9.1 静态查找表9.2 动态查找表9.3 哈希表,2020/3/13,3,查找的基本概念,查找又称为查询或检索,是在一批记录中依照某个域的指定域值,找出相应的记录的操作。 在计算机中,被查找的数据对象是由同一类型的记录构成的集合,可称之为查找表(search t

2、able)。 在实际应用问题中,每个记录一般包含有多个数据域,查找是根据其中某一个指定的域进行的,这个作为查找依据的域称为关键字(key)。,2020/3/13,4,对于给定的关键字的值,如果在表中经过查找能找到相应的记录,则称查找成功,一般可输出该记录的有关信息或指示该记录在查找表中的位置。若表中不存在相应的记录,则称查找不成功,此时应该给出不成功的信息。 查找算法中的基本运算是记录的关键字与给定值所进行的比较,其执行时间通常取决于比较的次数。因此,通常以关键字与给定值进行比较的记录个数的平均值,作为衡量查找算法好坏的依据。,2020/3/13,5,查找表操作及分类,操作:(1)查询某个“特

3、定的”数据元素是否在查找表中;(2)某个“特定的”数据元素的各种属性;(3)在查找表中插入一个数据元素;(4)从查找表中删去某个数据元素。 分类:若对查找表只作(1)和(2)两种操作,则称此类查找表为静态查找表。若在查找过程中同时插入查找表中不存在的数据元素,或者从查找表中删除已存在的某个数据元素,则称此类查找表为动态查找表。,2020/3/13,6,9.1 静态查找表,抽象数据类型静态查找表的定义:ADT StaticSearchTable数据对象D: D是具有相同属性的数据元素的集合。数据关系R:数据元素同属一个集合。基本操作P: Create( ADT StaticSearchTable

4、,2020/3/13,7,一、顺序查找,顺序查找的基本思想是:从线性表的一端开始,依次将扫描到得结点关键字和给定值K相比较。若当前扫描到得结点关键字与K相等,则查找成功;若扫描结束后,仍未找到关键字等于K的结点,则查找失败。 顺序查找的存储结构要求:顺序查找方法既适用于线性表的顺序存储结构,也适用于线性表的链式存储结构(使用单链表作为存储结构时,扫描必须从第一个结点开始),顺序查找对数据在表中存放的先后次序没有任何要求。,在表的组织方式中,线性表是最简单的一种。顺序查找是一种最简单的查找方式。,2020/3/13,8,顺序查找的线性表定义如下:typedef struct ElemType *

5、elem;int length; ;,每个结点包含两部分内容:Key 和info,其他信息,2020/3/13,9,(2)算法的实现:,技巧:把待查关键字key存入表头或表尾(俗称“哨兵”),这样可以加快执行速度。,例:,若将待查找的特定值key存入顺序表的首部(如0号单元),则顺序查找的实现方案为:从后向前逐个比较!,int Search_Seq( SSTable ST , KeyType key )/在顺序表ST中,查找关键字与key相同的元素;若成功,返回其位置信息,否则返回0ST.elem0.key =key; /设立哨兵,可免去查找过程中每一步都要检测是否查找完毕,0单元被当作监视哨

6、,用来判断表是否查找完毕(技巧)。当n1000时,查找时间将减少一半。for( i=ST.length; ST.elem i .key!=key; - - i );/不要用for(i=n; i0; - -i) 或 for(i=1; i=n; i+) return i; /若到达0号单元才结束循环,说明不成功,返回0值(i=0)。成功时则返回找到的那个元素的位置i。 / Search_Seq,监视哨的作用: 无需判断是否越界.,选择0当作监视哨,因为在数组里面0单元处理比较麻烦,不小心就出错,2020/3/13,10,顺序查找的算法: int Search_seq(SSTable ST , in

7、t n, int key) int i=n;ST0.key=key;for( i=ST.length; ST.elem i .key!=key; - - i );/*从表尾往前查*/return i; ,监视哨,for(i=n; i0; - -i) if(ST.elem i .key=key)return i; ,使用了监视哨,在查找过程中,不用每一步都去判断是否查找结束。0单元被当作监视哨,用来判断表是否查找完毕(技巧)。当n1000时,查找时间将减少一半。 找到:返回元素在线性表中的存储位置; 未找到:返回0。,2020/3/13,11,查找效率怎样计算? 用平均查找长度ASL衡量。,讨论

8、,平均查找长度:为确定记录在查找表中的位置,需和给定值进行比较的关键字个数的期望值称为查找算法在查找成功时的平均查找长度(Average Search Length)。,2020/3/13,12,平均查找长度(ASL:average search length)。,其中: n是文件记录个数; Pi是查找第i个记录的查找概率(通常取等概率,即Pi =1/n); Ci是找到第i个记录时所经历的比较次数。,统计意义上的数学期望值,物理意义:假设每一元素被查找的概率相同,则查找每一元素所需的比较次数之总和再取平均,即为ASL。,显然,ASL值越小,时间效率越高。,2020/3/13,13,讨论如何计算

9、ASL?,分析: 查找第1个元素所需的比较次数为1; 查找第2个元素所需的比较次数为2; 查找第n个元素所需的比较次数为n;,总计全部比较次数为:12n = (1+n)n/2,未考虑查找不成功的情况:查找哨兵所需的比较次数为n+1,这是查找成功的情况,若求某一个元素的平均查找次数,还应当除以n(等概率), 即: ASL(1n)/2 ,时间效率为 O(n),2020/3/13,14,如果查找不成功的情况不能忽略时:,ASL的计算步骤:,查找成功的概率为1/2;那么查找成功时第i个记录的概率pi=1/2n,所以查找成功时的ASL= (n-i+1)= (n+1),n,i=1,1,2n,4,1,1,2

10、,_,查找不成功的概率为1/2;所以查找不成功时的ASL= (n+1),所以:ASLss=3/4(n+1),2020/3/13,15,顺序查找算法分析,顺序查找的优点是算法简单、适应面广,且不要求表中数据有序。缺点是平均查找长度较大,特别是当n较大时,查找效率较低,不宜采用。,2020/3/13,16,二、有序表的查找(折半查找),折半查找(Birary search)也称为二分查找,它的查找速度比顺序查找快,但它要求数据在线性表中按查找的关键字域有序排列。 设n个数据存放于数组r中,且已经过排序,按由小到大递增的顺序排列。 采用二分查找,首先用要查找的给定值k与表正中间元素的关键值相比较,此

11、元素的下标:,2020/3/13,17,比较结果有三种可能: 如果rm.keyk,说明如果存在欲查找的元素,该元素一定在数组的前半部分,查找范围缩小了一半,修改查找范围的的上界high=m-1,继续对数组的前半部分进行二分查找; 如果rm.keyk,说明如果存在欲查找的元素,该元素一定在数组的后半部分,查找范围缩小了一半,修改查找范围的的下界low=m+1,继续对数组的后半部分进行二分查找; 如果rm.key=k,查找成功,m所指的记录就是查找到的数据。,2020/3/13,18,重复上述过程,查找范围每次缩小1/2,当范围不断缩小,出现查找范围的下界大于上界时,则查找失败,确定关键字为key

12、的记录不存在。 二分查找是一种效率较高的算法,最好的情况是第一次比较即找到所查元素,即使一次比较没有找到,也把进一步查找的范围缩小一半。与此类似,每比较一次均使查找范围减半,故最坏的情况所需比较次数为O(log2n),对于较大的n显然较顺序查找速度快得多。,2020/3/13,19,查找23和79的过程如下图:,mid=(low+high)/2不进位取整,( 08, 14, 23, 37, 46, 55, 68, 79, 91 ),( 08, 14, 23, 37, 46, 55, 68, 79, 91 ),( 08, 14, 23, 37, 46, 55, 68, 79, 91 ),( 08

13、, 14, 23, 37, 46, 55, 68, 79, 91 ),( 08, 14, 23, 37, 46, 55, 68, 79, 91 ),( 08, 14, 23, 37, 46, 55, 68, 79, 91 ),( 08, 14, 23, 37, 46, 55, 68, 79, 91 ),2020/3/13,20,折半查找的c语言算法程序: int Search_Bin( SSTable ST , int n, int key) int low, high,mid;low=1; high=n;while(low=high) mid=(low+high)/2;if(STmid.ke

14、y= = key) return (mid); /*查找成功*/else if( key STmid.key) high=mid-1; /*在前半区间继续查找*/else low=mid+1; /*在后半区间继续查找*/return (0); /*查找不成功*/,2020/3/13,21,5、二分查找判定树,上述查找过程可以用二叉树来描述先看一个具体的情况,假设:n=11,1,2,2,3,3,3,3,4,4,4,4,判定树,6,3,9,1,4,7,10,2,5,8,11,一般情况下,表长为n的折半查找的判定树的深度和含有n个结点的完全二叉树的深度相同 log2n +1,2020/3/13,22

15、,假设n=2h-1并且查找概率相等 则,在n50时,可得近似结果,ASLbs 2(n+1)-1,2020/3/13,23,二分查找的性能分析,具体例子(11个元素) 查找过程可用判定树描述 查找成功时进行比较的关键字个数最多不超过树的深度log2n +1 当n较大时,平均查找长度为ASLbs= log2( n+1) 1,6,3,1,9,4,7,10,2,5,8,11,2020/3/13,24,三、静态树表的查找,当有序表中各记录的查找概率相等时,按照判定树描述的查找过程来进行折半查找,性能最优;有序表中各记录的查找概率不等时,二分查找性能不一定最优。可由具体例子说明。静态最优查找树和次优查找树

16、方法可解决这一问题。,2020/3/13,25,例如,关键字: A B C D E ci: 2 3 1 2 3,此时:ASL=20.2+30.3+10.05+20.3+30.15=2.4,若改变ci的值: 2 1 3 2 3,则: ASL=20.2+10.3+30.05+20.3+30.15=1.9,不是中间的比,而是根据概率值得不同具体选择。,C,A,D,B,1,2,3,4,5,pi: 0.2 0.3 0.05 0.3 0.15,E,2020/3/13,26,在概率不等的情况下:如何能够使平均查找长度最小?,查找概率大的查找路径要短,判定树该如何设计,其中,wi=cpi,c为常量,pi为结点

17、i的查找概率,hi为结点所在的层次,称PH值最小的判定二叉树为静态最优查找树。(这里只考虑查找成功的情况),如果只考虑查找成功的情况,则使查找性能达到最佳的判定树是其带全路径长度之和PH值,取最小的二叉树,2020/3/13,27,构建静态最优查找树的代价很高,这里介绍一种构造近似最有树的算法 次优查找树。,二、次优查找树的构造,已知一个序列:(rl,rl+1,,rh),递增有序其中 :rl.key rl+1.key rh.key 它对应的权值为:(wl,wl+1,wh),现构造一棵二叉树,使这棵二叉树的带权路径长度PH值在所有具有同样权值的二叉树中近似最小,称这类二叉树为次优查找树。,202

18、0/3/13,28,取Pi最小的那个元素i作为根,然后分别对子序列(rl,rl+1, ,ri-1)和(ri+1,ri+2, ,rh)同样构造次优查找树,并分别作为i的左子树和右子树,计算Pi时,实际上就是计算元素i前面的元素权值之和和元素i后面的元素的权值之和的差值。,构造次优查找树的方法:首先在记录序列中取第i个记录构造根结点,关键字: A B C D Epi: 0.2 0.3 0.05 0.3 0.15,2020/3/13,29,21,18,12,4,3,10,18,A,B,C,D,E,F,G,9,6,0,8,1,2,5,3,E,C,2020/3/13,30,为了便于计算Pi,引入累计权值

19、之和,并设w0=0,sw0=0,则,wj=swi-1-swl-1,i-1,j=l,wj=swh-swi,h,j=i+1,Pi= | (swh+swl-1)-swi-swi-1 |,2020/3/13,31,0,2,3,8,11,15,18,23,21,18,12,4,3,10,18,A,B,C,D,E,F,G,9,6,0,8,1,2,5,3,Pi= | (swh+swl-1)-swi-swi-1 |,E,C,2020/3/13,32,四、分块查找(索引顺序查找),这是一种顺序查找的另一种改进方法。 先让数据分块有序,即分成若干子表,要求每个子表中的数值(用关键字更准确)都比后一块中数值小(但子

20、表内部未必有序)。 然后将各子表中的最大关键字构成一个索引表,表中还要包含每个子表的起始地址(即头指针)。,索引表,最大关键字,起始地址,第1块,第2块,第3块,22,48,86,例:,特点:块间有序,块内无序,2020/3/13,33,查找步骤分两步进行:, 对索引表使用折半查找法(因为索引表是有序表); 确定了待查关键字所在的子表后,在子表内采用顺序查找法(因为各子表内部是无序表); 查找效率:ASL=Lb+Lw,对索引表查找的ASL,对块内查找的ASL,S为每块内部的记录个数,n/s即块的数目,例如当n=9,s=3时,ASLbs=3.5,而折半法为3.1,顺序法为5,2020/3/13,

21、34,9.2 动态查找表,特点:表结构本身是在查找过程中动态生成的。 抽象数据类型动态查找表的定义ADT DynamicSearchTable数据对象D:D是具有相同特性的数据元素的集合。数据关系R:数据元素同属一个集合。基本操作 P: InitDSTable; DestroyDSTable;SearchDSTable; InsertDSTable;DeletdDSTable;TraverseDSTable,2020/3/13,35,二叉排序树,定义:二叉排序树(Binary Sort Tree)或者是一棵空树;或者是具有下列性质的二叉树: (1)若它的左子树不空,则左子树上所有结点的值均小于

22、它的根结点的值; (2)若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;(3)它的左、右子树也分别为二叉排序树。,2020/3/13,36,二叉排序树举例,45,12,3,53,37,50,98,8,43,1,60,CAO,DING,ZHAO,CHEN,WANG,MA,2020/3/13,37,二叉排序树查找,将原始数据表示成二叉排序树,树的每个结点对应一个记录,则可利用此二叉排序树进行类似于二分查找思想的数据查找,这也是一个逐步缩小查找范围的过程。这种查找方法称为树型查找。 基本思想:查找过程从根结点开始,首先将它的关键字与给定值k进行比较,如果相等,则查找成功,输出有关的信息

23、;如果不等,若根结点关键字大于给定值k,向左子树继续查找,否则向右子树继续查找。 向子树查找又是树型查找,先以子树的根结点数据与k进行比较,如果不相等又转向它的左或右子树继续查找。,2020/3/13,38,树型查找是一种递归的查找过程。 在二叉排序树上查找关键字为k的结点,成功时返回该结点位置,否则返回NULL,递归函数如下: btree *search (btree *b,int k) if (b=NULL)return (NULL);elseif(b-data=k)return (b);,2020/3/13,39,二叉排序树查找递归算法,if(kdata) return (search

24、(b-left,k);else return (search (b-right,k);,2020/3/13,40,非递归算法,btree *treesearch (btree *b,int k) btree *p;p=b;while(p!=NULL); if (p-data=k) return (p);else if (kdata)p=p-left;else p=p-right;return (NULL);,2020/3/13,41,二叉排序树的插入,二叉排序树是一种动态树表。特点是树的结构不是一次生成,而是在查找过程中,当树中不存在关键字等于给定值的结点时再进行插入。 新插入的结点一定是一个

25、新添加的叶子结点,并且是查找不成功时查找路径上访问的最后一个结点的左孩子或右孩子结点。,2020/3/13,42,二叉排序树的插入(续),从空树出发,经过一系列的查找插入操作之后,可生成一棵二叉排序树。 设查找的关键字序列为45,12,53,3,37,50, 98,1,8,43,60,则生成的二叉排序树如下 中序遍历二叉排序树可得到一个关键字的有序序列。 插入时,不必移动结点。,45,12,3,53,37,50,98,8,43,1,60,2020/3/13,43,二叉排序树的删除,一般二叉树删除存在的问题。 如何在二叉排序树上删除结点?设在二叉排序树上被删结点为*p,其双亲结点为*f,又*p是

26、*f的左孩子。 若*p为叶子结点,其左右子树为空。此时只需修改*f的指针。 若*p只有左子树PL或只有右子树PR ,此时只要令PL或PR直接成为其双亲结点*f的左子树即可。,2020/3/13,44,二叉排序树的删除(续),若*p的左子树PL和右子树PR 均不空。根据图示可知,在删去*p之前,中序遍历该二叉树得到的序列为CLC QLQ SLS PPRF ,在删去*p之后,仍应保持其它元素的相对位置不变,方法一是令*p的左子树为*f的左子树,而*p的右子树为*s的右子树;方法二是令*p的直接前驱(或直接后继)替代*p,然后再从二叉排序树中删去它的直接前驱(或直接后继)。,2020/3/13,45

27、,二叉排序树的删除图示,F,P,f,p,PL,PR,F,P,f,p,CL,PR,f,C,Q,S,QL,SL,F,C,f,c,CL,PR,f,Q,S,QL,SL,c,2020/3/13,46,在二叉排序树上进行查找,若查找成功,则是从根结点出发走了一条从根结点到所查找结点的路径;若查找不成功,则是从根结点出发走了一条从根结点到某个终端叶子结点的路径。与二分查找类似,和关键字比较的次数不超过二叉排序树的深度。 但是,含有n个结点的二叉树不是唯一的,由于对其结点插入的先后次序不同,所构成的二叉树的形态和深度也可能不同。例如,下页图是按不同插入次序得到的两个二叉排序树。,二叉排序树查找分析,2020/

28、3/13,47,两个二叉排序树,在查找失败的情况下,在这二个树上所进行的关键字比较次数分别为3和6次。,2020/3/13,48,二叉排序树查找分析(续),树型查找最坏情况时,需要的查找时间取决于树的高度,当二叉排序树接近满二叉树时,其高度为log2n,最坏情况下查找时间为O(log n),与二分查找是同样数量级的;当二叉排序树为只有一个端结点的所谓“退化树”时,其高度等于n,最坏情况下查找时间为O(n),与顺序查找属于同一数量级。 为了保证树型查找有较高的查找速度,我们希望该二叉树接近满二叉树,也就是希望二叉树的每一个结点的左、右子树高度尽量接近平衡,即使按任意次序不断地插入结点,也不要使此

29、树成为退化树。,2020/3/13,49,平衡树,平衡树(Balanced tree)也称为AVL树,是由阿德尔森维尔斯基和兰迪斯(Adelson-velskii and landis)于1962年首先提出的。 这是一种附加了一定限制条件的二叉树。我们定义二叉树中每一结点的左子树高度减右子树高度为该结点的平衡因子(Balance factor),所谓平衡树,是指一个二叉树其任一结点的平衡因子值只能是+1,0或-1,即任一结点的左、右子树高度之差不超过1。 如下页图所示,图中数字为该结点的平衡因子。,2020/3/13,50,平衡树,平衡二叉树,不平衡二叉树,2020/3/13,51,假设给平衡

30、树某个结点的左子树插入一个新结点,且此新结点使左子树的高度加1,我们可能会遇到以下三种情况: (1) 如果原来其左子树高度hl与右子树高度hr相等,即原来此结点的平衡因子等于0,插入新结点后将使平衡因子变成+1,但仍符合平衡树的条件,不必对其加以调整; 如果原来hlhr,即原来此结点的平衡因子等于+1,插入新结点后将使平衡因子变成+2,破坏了平衡树的限制条件,需对其加以调整; 如果原来hlhr,即原来此结点的平衡因子等于-1,插入新结点后将使平衡因子变成0,平衡更加改善,不必加以调整。,2020/3/13,52,如果给平衡树某结点的右子树插入一个结点,且设此新结点使右子树的高度增加1,则也会遇

31、到与之相对应的三种情况。 以下页图所示的树为例,设原已有关键字为51,29,72,11和46这五个结点,原树符合平衡树条件,图中各结点旁所标数字为该结点的平衡因子。,2020/3/13,53,平衡树插入结点,2020/3/13,54,插入新结点破坏了平衡树条件的情况分为两类,仍以向左子树插入新结点为例,这两类情况分别如下页图(a)和(c)所示。 图中矩形表示子树,矩形的高度表示子树的高度,带阴影线的方形则表示插入新结点后造成的子树高度加1,各结点旁所标数字为该结点的平衡因子。,2020/3/13,55,平衡树的调整图,2020/3/13,56,2020/3/13,57,平衡树以二叉链表作为存储

32、结构,每个结点还要增加一个平衡因子域。 平衡树的查找运算与普通树型查找完全相同,由于平衡树附加了平衡条件,其高度与结点数相同的完全树属于同一数量级,所以有较快的查找速度。 在插入新结点时,当确定了新结点应插入的位置后,需向回寻找有关平衡因子变为+2或-2的祖先,如有这种结点,则取其中层数居最低者,根据不同的情况进行单旋转或双旋转,使整个树仍然符合平衡树的条件,每次插入结点后,还需对有关祖先的平衡因子加以修改。,2020/3/13,58,B-树,前面介绍的查找方法,均适用于查找存储在内存中的数据,统称为内查找方法,它们适用于较小的表,而对较大的、存储在外存储器上的文件就不合适了。 B-树是一种多

33、路平衡查找树,这是一种适用于外查找的方法的数据结构。 B-树的定义:一棵m(m3)阶的B-树,或者为空树,或者是满足如下条件的m叉树:,2020/3/13,59,(1)树中每个非终端结点至少包含以下数据项:(n,A0,K1,A1,K2,Kn,An)其中,n为关键字总数,Ki(1in)是关键字,Ai是指向子树根结点的指针。关键字是递增有序的:K1K2Kn,且Ai(0in)所指子树中所有结点的关键字均小于Ki+1,An所指子树中所有结点的关键字均大于Kn。 (2)所有的叶子结点都在同一层上,并且不带信息(可以看作是外部结点或查找失败的结点,实际上这些结点不存在,指向这些结点的指针为空)。,B-树定

34、义,2020/3/13,60,(3)每个非根结点中所包含的关键字个数n满足 -1 nm-1,即每个非根结点至少应有 个关键字,至多有m-1个关键字。因为每个内部结点的度数正好是关键字数加1,故每个非根的内部结点至少有 棵子树,至多有m棵子树。 (4)如果树非空,则根至少有1个关键字,所以如果根不是叶结点,则至少有两棵子树。最多有m-1个关键字,所以最多有m棵子树。,2020/3/13,61,一棵4阶B-树,2020/3/13,62,9.3 哈希表,集合结构-查找表是一种非常灵便的数据结构,关系松散,给查找带来不便。为此,需在数据元素之间人为地加上一些关系,以便按某种规则进行查找,即以另一种数据

35、结构来表示查找表。 在线性表、树表中,记录在结构中的相对位置是随机的,查找时需进行一系列的比较,查找的效率依赖于查找过程中所进行的比较次数。,2020/3/13,63,哈希表,理想情况是不经过任何比较,一次存取便能得到所查记录,需在记录的存储位置和它的关键字之间建立一个确定的对应关系。从关键字集合到地址集合的对应关系f称为哈希函数或散列函数(Hashed Function) 。按这个思想建立的表称为哈希表(hashed table) 。 f(K)的值称为哈希地址或散列地址。 哈希查找(Hashed search)为在哈希表上进行查找的过程,也称为散列法或杂凑法。,2020/3/13,64,设有

36、关键字为1,3,7,12,15的五个记录,定义一个散列函数为:h(k)=(k mod m)+1式中k为关键字,mod表示除法取余数的运算,m为一项规定的整数。 假设在此我们取m=7,则按这五个关键字计算出的函数值为:h(1)=2,h(3)=4,h(7)=1,h(12)=6,h(15)=2,2020/3/13,65,散列法,可能由不同的关键字计算出相同的散列函数值来,例如此例中h(1)和h(15)都等于2,也就是遇到了不同记录占用同一地址单元的情况,这种情况称为发生了冲突(collision)。 具有相同函数值的关键字对该哈希函数来说称为同义词(synonym)。,2020/3/13,66,散列

37、是一种重要的存储方法,又是一种查找方法。 应用散列法存储记录的过程是对每个记录的关键字进行散列函数的运算,计算出该记录存储的地址,并将记录存入此地址中。 查找一个记录的过程与存储记录的过程一样,就是对待查找记录的关键字进行计算,得到地址,并到此地址中查找记录是否存在。 散列存储的两个关键问题:如何尽量避免冲突和如何解决冲突。,2020/3/13,67,哈希函数构造方法,目标是使散列地址尽可能均匀地分布在散列空间上,同时使计算尽可能简单,以节省计算时间。 直接定址法:直接取关键字本身或者关键字加上一个常数作为散列地址。适用于关键字的分布基本连续的情况。例子见教材。 数字分析法:又称为数字选择法。

38、适用于所有关键字事先都知道,并且关键字的位数比散列地址的位数多的情况,在这种情况下,可将各个关键字列出,分析它们的每一位数字,舍去各关键字取值比较集中的位,仅保留取值比较分散的位作为散列地址。,2020/3/13,68,数字分析法例子,2020/3/13,69,哈希函数构造方法,除留余数法:用关键字除以不大于哈希表表长m的数p除后所得余数为哈希地址。即 H(key)=key MOD p, pm 这是一种最简单也最常用的构造散列函数的方法。这种方法关键在于p的选择,若p选的不好,容易出现冲突。 由经验知:一般情况下,可以选为质数或不包含小于20的质因数的和数。,2020/3/13,70,哈希函数

39、构造方法,平方取中法:取关键字平方后的中间几位为哈希地址。在不知道关键字全部情况时常用。 折叠法:折叠法是将关键字按要求的长度分成位数相等的几段,最后一段如不够长可以短些,然后把各段重叠在一起相加并去掉进位,以所得的和作为地址。 随机数法:选择一个随机函数,取关键字的随机函数值为它的哈希地址。当关键字长度不等时采用此方法较恰当。 采用不同的哈希函数应考虑的五个因素。,2020/3/13,71,处理冲突的方法,假设哈希表的地址集为0n-1,冲突是指由关键字得到的地址为j(0j n-1)的位置上已存有记录,则处理“冲突”就是为该关键字的记录找到另一个“空”的记录。 开放地址法:开放地址就是表中尚未

40、被占用的地址,当新插入的记录所选地址已被占用时,即转而寻找其它尚开放的地址。 形成探查地址序列最简单的方法是线性探测法,设散列函数为H,闭散列表一维数组的容量为m,对关键字k,计算出的地址为d=H(k)。,2020/3/13,72,处理冲突的方法(续),线性探测法的基本思想是沿着散列表顺序向后探查,直至找到开放地址为止,如到达表末端仍未找到开放地址,则将表看成是循环的,返回到表的首端再向后找,只要尚有开放地址最终总可以找到。 线性探测法对应的探查地址序列为d+1,d+2,m,1,d-1。探查地址序列对应的计算公式为:di=(H(K)+i) mod m (1im-1),2020/3/13,73,

41、例如,已知一组关键字k1k5,已计算出各关键字的散列函数值为:H(k1)=3, H(k2)=5, H(k3)=1, H(k4)=3, H(k5)=3,总记录个数为5,开辟的一维数组长度可以比实际用的存储单元多一些,取m=8。,2020/3/13,74,开放地址的线性探测,2020/3/13,75,二次探测法,二次探测法的基本思想是:生成的探查地址序列不是连续的,而是跳跃式的。二次探测法对应的探查地址序列的计算公式为:di = (H(k)+i) mod m 其中i=12,-12,22,-22,j2,-j2,(jm/2)。随机探测法:I为伪随机数序列。,2020/3/13,76,开放地址的二次探测

42、,2020/3/13,77,链地址法:设散列函数为H(k),函数值范围为0m-1,散列表的结构可以设计成一个由m个指针域构成的指针数组Tm,初始状态都是空指针。其中每一个分量对应一个单链表的头指针,凡散列地址为i的记录都插入到头指针为Ti的链表中。每一个这样的单链表称为一个同义词表。链地址法解决冲突的方式,就是将所有关键字为同义词的记录链接在同一个单链表中。同义词要求按关键字有序。 其它处理冲突的方法:再哈希法和建立公共溢出区。 例如前面的例子改用链地址法如下页图所示。,2020/3/13,78,链地址法,2020/3/13,79,散列法的查找运算,散列表的目的主要是用于快速查找。 在建表时采

43、用何种散列函数及何种解决冲突的办法,在查找时,也采用同样的散列函数及解决冲突的办法。假设给定的值为k,根据建表时设定的散列函数H,计算出散列地址H(k),如果表中该地址单元为空,则查找失败;否则将该地址中的关键字值与给定值k比较,如果相等则查找成功,否则按建表时设定的处理冲突的方法找下一个地址,如此反复下去,直到某个地址单元为空(查找失败)或与关键字值比较相等(查找成功)为止。,2020/3/13,80,设有一批正整数关键字,采用除留余数的散列函数和线性探测开放地址的办法解决冲突,存放入长度约为该批数据总数1.5倍的一维数组A中,因为关键字值均大于0,所以规定数组元素置0表示开放地址。 要求当

44、查找成功时,给出与该关键字相应的地址,查找失败时则将该关键字插入开放地址单元并输出此地址。待查找的关键字为k,m值取一个接近数组长度的质数,则这种散列法的查找算法如下:,2020/3/13,81,查找算法,int Hashing (int A,m,k) int i; /*为散列函数值*/i=(k mod m)+1while (Ai!=k /*i未到达表末端则后移一个单元进行线性探测,否则返回到表首端继续探测,直至找到待查关键字k或者遇到开放地址为止*/,2020/3/13,82,查找算法续,if(Ai=0) Ai=k;return (i); ,2020/3/13,83,例1,设有一组关键字19

45、,01,23,14,55,20,84,27,68,11,10,77,采用哈希函数:H(k)=k mod 13。采用开放地址的线性探测法解决冲突,试在018的散列地址空间中,对该关键字序列构造散列表。 解:依题意m=19,得到线性探测法对应的探查地址序列计算公式为:di=(H(k)+j) mod 19; j=1,2,18其计算函数如下:H(19)=19 mod 13=6H(01)=01 mod 13=1,2020/3/13,84,H(23)=23 mod 13=10H(14)=14 mod 13=1 (冲突)H(14)=(1+1) mod 19=2H(55)=55 mod 13=3H(20)=2

46、0 mod 13=7H(84)=84 mod 13=6 (冲突)H(84)=(6+1) mod 19=7 (冲突)H(84)=(6+2) mod 19=8H(27)=27 mod 13=1(冲突)H(27)=(1+1) mod 19=2 (冲突),2020/3/13,85,H(27)=(1+2) mod 19=3 (冲突)H(27)=(1+3) mod 19=4H(68)=68 mod 13=3 (冲突)H(68)=(3+1) mod 19=4 (冲突)H(68)=(3+2) mod 19=5H(11)=11 mod 13=11H(10)=10 mod 13=10 (冲突)H(10)=(10+

47、1) mod 19=11 (冲突)H(10)=(10+2) mod 19=12H(77)=77 mod 13=12 (冲突)H(77)=(12+1) mod 19=13,2020/3/13,86,例地址分配,2020/3/13,87,查找效率分析,哈希表的查找效率仍以平均查找长度量度。其中平均查找长度为每个元素的查找长度之和除以所有元素的个数。 比较次数取决于下列三个因素:哈希函数、处理冲突的方法和哈希表的装填因子。 哈希表的装填因子定义为 = 表中填入的记录数 / 哈希表的长度最好在0.60.9之间。,2020/3/13,88,查找效率分析(续),线性探测再散列的哈希表查找成功时的平均查找长度为 Snl (1+1/(1- )/2 随机探测再散列、二次探测再散列和再哈希的哈希表查找成功时的平均查找长度为 Snr -ln(1- )/ 链地址法处理冲突的哈希表查找成功时的平均查找长度为 Snc 1+ /2 哈希表在查找不成功时的讨论略,2020/3/13,89,查找的应用实例,“口令”或“密码”的查找 计算机病毒的检测技术 在“电信通话记录”中的查找,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报