散列查找--解决冲突的方法
常用的处理冲突的方法:开放定址法,分离链接法。
因为是期末复习(●ˇ∀ˇ●),浅浅地记个开放定址法的线性探测法和平方探测法;
例:
设关键字序列{47,7,29,11,9,84,54,20,30},散列表表长TableSize=13,散列函数为:h(key)=key mod 11。
萌新瞎补:
散列表表长:对于一串数,就看做一个整形数组来存这些数,TableSize就是数组的大小;
散列函数:咳咳,这是之前的知识啊!就是本来是这个数,通过一种关系变成了另外一个数,比如为了实现离散化操作。
ok,继续。
线性探测法:
见表:
关键字 | 47 | 7 | 29 | 11 | 9 | 84 | 54 | 20 | 30 |
散列地址 | 3 | 7 | 7 | 0 | 9 | 7 | 10 | 9 | 8 |
冲突次数 | 0 | 0 | 1 | 0 | 0 | 3 | 1 | 3 | 6 |
可见啊,有些关键字对应的散列地址有冲突!
线性 探测 上
所谓线性,就是对于原冲突散列地址+1再往散列函数搞搞,h(new)=(h(old)+1)%13,其实很显然就是往他右边看看,如果右边没有就在右边住下了,如果右边还有持续往右,但是注意,最右边的时候,本来式子就是取膜啊,所以就是往回看起,就是这么一步一步的探测,找空位子。
平均查找长度(ASL):就是一共找了几次然后除以关键字的个数。比如:上面的例子:ASL=(1+1+2+1+1+4+2+4+7)/9≈2.56;
平方探测法:
这个据说比线性好,我们能在线性探测法看到,如果连续一段都已经被占了,那么线性的话(也就是+1的话)有点慢啊。
这个时候,平方 探测 出场。
线性不是每次+1取膜么?平方就是如果“聚集”,我是加一个数k的平方,而且这个k会越来越大,而且线性只往右边(其实是往右的循环),平方是往两端,具体序列是:
+1^2,-1^2,+2^2,-2^2,+3^2,-3^2,...,+k^2,-k^2 这样的话找的更快啊!
有证据(略)表明:TableSize如果是4x+3(x是正整数)形式的素数,平方探测法就可以探查到整个散列表空间;
有一题譬如:PAT1078
题目是严格向右探测的:
贴一小段代码,当找不到的时候,注意+k^2 并取膜;
有一题譬如:PAT1078
题目是严格向右探测的:
贴一小段代码,当找不到的时候,注意+k^2 并取膜;
bool flag=false; int inc=1; while(inc<Size) { int tmp=(x+inc*inc)%Size; if(mp.find(tmp)==mp.end()) { mp[tmp]=1; a[i]=tmp; flag=true; break; } inc++; } if(!flag) a[i]=-1;
OK,THAT'S ALL;