2017-07-28 16:01:16
writer:pprp
哈希表:通过节点储存位置和其关键字建立某种直接关系,使得查找的时候无需作比较或者做很少次数的比较就能找到相应的记录;
哈希函数的几种构造方法:
- 数学分析法:分析一组数据,比如一组员工的出生年月日,这时我们发现出生年月日的前几位数字大体相同,这样的话,出现冲突的几率就会很大,但是我们发现年月日的后几位表示月份和具体日期的数字差别很大,如果用后面的数字来构成散列地址,则冲突的几率会明显降低。因此数字分析法就是找出数字的规律,尽可能利用这些数据来构造冲突几率较低的散列地址。
- 除留余数法:取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址。即 H(key) = key MOD p,p<=m。不仅可以对关键字直接取模,也可在折叠、平方取中等运算之后取模。对p的选择很重要,一般取素数或m,若p选的不好,容易产生同义词。
- 直接寻址法:取关键字或关键字的某个线性函数值为散列地址。即H(key)=key或H(key) = a·key + b,其中a和b为常数(这种散列函数叫做自身函数)。若其中H(key)中已经有值了,就往下一个找,直到H(key)中没有值了,就放进去。
自己制定规则的哈希表
代码如下:
//d = H(K) = 3K%11 //d = (d+(7K%10)+1)%11 #include <iostream> using namespace std; const int M = 11; const int N = 7; struct term { int key; //关键字值 int si; //散列次数 }; struct term hashlist[M+1]; int i,address,sum,d,x[N+1]; float average; int main() { for(i=1; i<=M; i++) { hashlist[i].key=0; hashlist[i].si=0; } x[1]=22,x[2]=41,x[3]=53,x[4]=46,x[5]=30,x[6]=13,x[7]=1; for(i=1;i<=N;i++) { sum=0; address=(3*x[i])%11; d=address; if(hashlist[address].key==0) //没有冲突 { hashlist[address].key = x[i]; hashlist[address].si = 1; } else { do { d = (d+(x[i]*7)%10+1)%11; sum+=1; }while(hashlist[d].key!=0); hashlist[d].key = x[i]; hashlist[d].si = sum+1; } } cout << "哈希列表: "; for(i=0;i<M;i++) { cout.width(4); cout << i; } cout << endl; cout << "哈希表关键字: "; for(i=0;i<M;i++) { cout.width(5); cout <<hashlist[i].key; } cout << endl; cout <<"搜索长度: "; for(i=0;i<M;i++) { cout.width(5); cout <<hashlist[i].si; } cout << endl; average=0; for(i=0;i<M;i++) average+=hashlist[i].si; average/=N; cout <<"平均搜索长度为: "<<average<<endl; return 0; }