收藏 分享(赏)

哈希表.ppt

上传人:j35w19 文档编号:4574421 上传时间:2019-01-02 格式:PPT 页数:22 大小:114KB
下载 相关 举报
哈希表.ppt_第1页
第1页 / 共22页
哈希表.ppt_第2页
第2页 / 共22页
哈希表.ppt_第3页
第3页 / 共22页
哈希表.ppt_第4页
第4页 / 共22页
哈希表.ppt_第5页
第5页 / 共22页
点击查看更多>>
资源描述

1、哈希表及其应用,一、什么是哈希表,现在要存储和使用下面的线性表:a=(1,75,324,43,1353,90,46)。那么,很简单,定义一个一维数组a1n,此处n=7,将表中元素按先后顺序存储在ai中,但这样给查找带来了开销,尤其是n很大时,我们需要用o(n)的时间去查找某个元素(当然也可采用二分查找提高效率);反之,为了用o(1)的时间实现查找,可以分析这个线性表的元素类型和范围,开一个一维数组a11353, 使得akey=key,即线性表的key这个元素存储在akey中,这样一来,查找的效率便为o(1)了,但显然造成了空间上的很大浪费,尤其是数据范围分布很广时。为了使空间开销减少,我们可以

2、对第二种方法加以优化,设计一个函数h(key)=key mod 13,然后把key存在ah(hey)中,这样一来定义一个一维数组a012就已足够,这种方法就是我们要学习的哈希表(散列表)。,哈希表是一种高效的数据结构。它的最大优点就是把数据存储和查找所消耗的时间大大降低,几乎可以看成是常数时间;而代价仅仅是消耗比较多的内存。然而在当前可利用内存越来越多、程序运行时间控制的越来越短的情况下,用空间换时间的做法还是值得的。另外,哈希表编码实现起来比较容易也是它的优点之一。 哈希表的主要操作就是存储数据和查找数据。,二、HASH函数的构造方法,我们使用一个下标范围比较大的数组来存储元素。可以设计一个

3、函数(哈希函数, 也叫做散列函数),使得每个元素的关键字都与一个函数值(即数组下标)相对应,于是用这个数组单元来存储这个元素;也可以简单的理解为,按照关键字为每一个元素“分类”,然后将这个元素存储在相应“类”所对应的地方。 几种常用的HASH函数的构造方法:(设 h(k) 表示关键字为 k 的元素所对应的函数值) 1、 取余法: 选择一个适当的正整数 p ,令 h(k ) = k mod p 这里, p 如果选取的是比较大的素数,效果比较好。P一般选择在K的值域12倍的范围内的素数。比如:K的值域为0600,那么P=701即为一个不错的选择。此法非常容易实现,因此是最常用的方法。这类函数主要适

4、用于整数。,二、HASH函数的构造方法,2、乘积取整法: 用关键字K乘以一个在(0,1)中的实数A(最好是无理数),得到一个(0,K)之间的实数;取出其小数部分,乘以M(M是哈希表的容量),再取乘积整数部分,即得在HASH表中的位置。函数表达式可以写成:h(k)=trunc(M*(frac(K*A) 这类函数主要适用于小数。,二、HASH函数的构造方法,3、字符串HASH函数: 字符串本身可以当作一个256进制的大数,所以可以转换成十进制的数采用第一种求HASH函数的方法直接取模,P通常取较大的素数。,三、HASH函数的冲突处理,无论什么HASH函数或多或少总会出现多个数据对应一个同一位置的情

5、况,我们称之为冲突。 处理冲突的方法:开散列和闭散列 开散列:把对应同一个位置的数据都放在这个位置,因此每个位置就相当于有一个链表存放属于该位置的所有数据。 闭散列:如果根据函数计算出来的位置已经存放了数据,那么顺次往后找(如果超过哈希表的容量则回到开头再继续),直到找到一个空位置存放该数据。,四、HASH函数的应用实例,【问题描述】 从文件中输入N(1N10000)个由小写英文字母组成的字符串,每个字符串的长度不超过200,统计它们出现的次数。 【输入】 第一行:N 从第二行到第N+1行,每行一个字符串。 【输出】 按输入顺序输出每个字符串及出现的次数。每行包括一个字符串和这个字符串出现的次

6、数,它们之间用一个空格隔开。,【输入样例】 10 abcde abc aabbc abcde abcde abc abc abcde aabbc abc,【输出样例】 abcde 4 abc 4 aabbc 2,分析,由于只有26个小写的英文字母,所以可以将字符串转化为26进制数确定其在HASH表中的位置,转化函数如下: function hcode(s:string):longint; var p,x,i:longint; beginp:=1; x:=0;for i:=length(s) downto 1 dobeginx:=(x+(ord(si)-64)*p) mod size;p:=p*

7、26 mod size;end;hcode:=x; end;,分析,将字符串插入到HASH表中,若冲突,采用闭散列的方法处理冲突。 function getnum(s:string):longint; var x:longint; beginx:=hcode(s);while (ax.str) and (ax.strs) dox:=(x+1) mod size;if ax.str= then ax.str:=s;getnum:=x; end;,主程序: for i:=1 to n dobeginreadln(t);tot:=getnum(t);if atot.num=0 thenbegin i

8、nc(j); bj.str:=t; bj.num:=tot; end;inc(atot.num);end; 其它: const maxn=10010;size=10007; type hash=recordstr:string200;num:longint;end; a,b:array0maxn of hash;,GAP,【问题描述】GAP是一种纸牌游戏。纸牌有花色,标号1-4,每种花色有7个数字,分别是1-7。每张牌的编号就是花色+数字。现在有一张48的网格,把这28张牌放入网格中。 初始状态,把最左边一列空下来,如右上表所示: 接下来开始进行移动操作,首先把每种花色的1放到对应每行最前面的

9、空列,如右下表所示。,GAP,接下来的操作,每次可以找空格的左边与其同色的后继放在此空格。比如,可以选择43放到42右边,但是27没有后继,所以没有纸牌能放在27右边的空格,27右边的右边的空格,因为左边没有纸牌,所以同样不能放上纸牌。 游戏结束时达到目标状态如下:现在给你初始状态,求最少的移动次数使得它达到目标状态。(我们所说的移动次数不包括最初把各个花色的1移动到最前面的4步),【输入样例】 17 16 15 14 13 12 11 27 26 25 24 23 22 21 37 36 35 34 33 32 31 47 46 45 44 43 42 41 【输出样例】 44,分析,因为题

10、目的约束条件很强,所以可以直接BFS. 在扩展时可能会产生很多种状态,所以可以用HASH来进行判重。 将题目中需要处理的表格转化为一个长度为32的字符串(网格中的每一个位置上的数字就用其做为ASCII码对应的字符所代替,空格的位置用1填充)作为一个状态。 对于扩展出来的新状态,我们就用字符串相应的HASH函数计算位置来存储。如果发现已经在HASH表中,就可以忽略此状态,这样就达到了判重的效果。,第一步:读入数据并调整每行行首元素。,for i:=1 to 4 dobeginfor j:=2 to 8 dobeginread(mapi,j);if (mapi,j mod 10=1) thenbe

11、gin mapmapi,j div 10,1:=mapi,j;mapi,j:=1;end;end;readln;,第二步:描述初始状态和目标状态。,for i:=1 to 4 dofor j:=1 to 8 dobegina1.str:=a1.str+chr(mapi,j);if j8 then ed:=ed+chr(i*10+j) else ed:=ed+chr(1);end;,while head1) and (ord(c) mod 10)7) thenbeginp:=;p:=p+chr(ord(c)+1);k:=pos(p,ahead.str);tmp:=ahead.str;tmpi:=

12、chr(ord(c)+1); tmpk:=chr(1);if ins(tmp) thenbegininc(tail);atail.str:=tmp;atail.num:=ahead.num+1;if tmp=ed thenbegin writeln(atail.num); close(input); close(output); halt end;end;end;end;end;end;,第三步:BFS,function hcode(s:string):longint; var p,x,i:longint; beginp:=1; x:=0;for i:=length(s) downto 1 d

13、obeginx:=(x+ord(si)*p) mod size;p:=p*26 mod size;end;hcode:=x; end; function ins(s:string):boolean; var x:longint; beginins:=false;x:=hcode(s);while (hashx) and (hashxs) dox:=(x+1) mod size;if hashx= thenbegin hashx:=s; exit(true);endelse exit(false); end;,练习:统计数字count.pas,【问题描述】 某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*109)。已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果。 【输入】 输入文件count.in包含n+1行; 第一行是整数n,表示自然数的个数; 第2n+1每行一个自然数。 【输出】 输出文件count.out包含m行(m为n个自然数中不相同数的个数),按照自然数从小到大的顺序输出。每行输出两个整数,分别是自然数和该数出现的次数,其间用一个空格隔开。,【输入输出样例】 count.in 8 2 4 2 4 5 100 2 100 count.out 2 3 4 2 5 1 100 2,

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

当前位置:首页 > 实用文档 > 统计图表

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


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

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

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