- 定义:
CuckooHash(布谷鸟散列)是为了解决哈希冲突问题而提出,利用较少的计算换取较大的空间。
- 特点: 占用空间少,查询速度快。
- 来源:
之所以起这个名字是因为布谷鸟生性贪婪,不自己筑巢,而是在别的鸟巢里面鸟蛋孵化,先成长的幼鸟会将别的鸟蛋挤出,这样独享“母爱”,类似于哈希冲突处理过程
- 算法描述:
使用hashA、hashB计算对应的key位置:
1、两个位置均为空,则任选一个插入;
2、两个位置中一个为空,则插入到空的那个位置
3、两个位置均不为空,则踢出一个位置后插入,被踢出的对调用该算法,再执行该算法找其另一个位置,循环直到插入成功。
4、如果被踢出的次数达到一定的阈值,则认为hash表已满,并进行重新哈希rehash
优化(减少哈希碰撞):
1、将一维改成多维,使用桶(bucket)的4路槽位(slot);
2、一个key对应多个value;
3、增加哈希函数,从两个增加到多个;
4、增加哈希表,类似于第一种;
cuckoo hash代码题目:
- 题目描述
整数哈希表是一种数据结构,支持在常量时间内插入,删除和查找整数值。传统的哈希结构由一些大小为n的数组(哈希表)和一个通常为f(x)= x mod n的哈希函数f(x)组成。为了在表中插入一个值x,你计算它的散列值f(x),它作为存储x的位置的哈希表中的索引。例如,如果x = 1234并且散列表具有大小101,则1234将被存储在位置22 = 1234 mod 101中。当然,可能的是其他一些值已经存储在位置22中(例如,x = 22) ,这会导致碰撞。可以通过多种方式处理碰撞,您可以在比赛回家的路上与您的教员顾问讨论。
杜鹃散列是一种散列形式,它使用两个散列表T1和T2,每个散列表都有自己的散列函数f1(x)和f2(x)。插入值x的过程如下:首先尝试使用f1(x)将x存储在T1中。如果该位置是空的,那么只需将x存储并完成。否则会发生必须处理的碰撞。设y是该位置当前的值。在T1中用x替换y,然后尝试使用f2(y)将y存储在T2中。再说一遍,如果这个位置是空的,你就在那里存储,你就完成了。否则,用y替换那里的值(称为z),然后尝试使用f1(z)将z存回T1中,依此类推。这个过程继续,在两张桌子之间来回跳动,直到你找到一个空的位置,或者直到有一定数量的掉期发生,此时你重新组合了这两张桌子(再次与你的教员顾问讨论)。出于这个问题的目的,后一种情况永远不会发生,即,该过程应该一直持续到找到一个空位置,这将保证每个插入的值发生。
鉴于两个表的大小和一系列插入,您的工作是确定每个表中存储的内容。
(对于那些有兴趣的人来说,杜鹃哈希的名字取决于杜鹃鸟的行为,该杜鹃鸟已知其他鸟类的巢穴,并将其自己的卵子与已经存在的鸡蛋一起放入其中。当较大的杜鹃小鸡孵化时,它会推动其他小鸡从巢中出来,从而得到所有的食物。可怕但有效。)
输入
每个测试用例的输入以3个正整数n1 n2 m开始,其中n1和n2是表T1和T2的大小(n1,n2≤1000和n1 6 = n2),m是插入的数量。接下来是m个整数值,它是要插入表中的值。所有这些值都是非负的。每个表最初是空的,表Ti使用散列函数fi(x)= x mod ni。包含3个零的行将终止输入。
输出
对于每个测试用例,在T1中输出非空位置,然后在T2中输出非空位置。对每个这样的位置和形式i:v使用一行,其中i是表的索引位置,v是存储在那里的值。每个表中的输出值从最低索引到最高。如果任一表为空,则不为该表输出任何内容。
样例输入
5 7 4
8 18 29 4
6 7 4
8 18 29 4
1000 999 2
1000
2000
0 0 0
样例输出
Case 1:
Table 1
3:8
4:4
Table 2
1:29
4:18
Case 2:
Table 1
0:18
2:8
4:4
5:29
Case 3:
Table 1
0:2000
Table 2
1:1000
代码实现:
• #include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main()
{
int n1,n2,m;
int a[1000];
int b=1;
int bq=1;
int h1[1005];
int h2[1005];
int cc=0;
while(scanf("%d %d %d",&n1,&n2,&m)!=EOF&&m!=0){
b=1;
bq=1;
memset(h1,0,sizeof(h1));
memset(h2,0,sizeof(h2));
for(int i=0;i<m;i++){
scanf("%d",&a[i]);
}
for(i=0;i<m;i++){
int locat=a[i]%n1;
int locat2=a[i]%n2;
if(b==1 && h1[locat]!=0){
int t=h1[locat];
h1[locat]=a[i];
a[i]=t;
i--;
b=2;
continue;
}
if(b==1 && h1[locat]==0){
h1[locat]=a[i];
if(bq==1){
bq=1;
b=1;
}else{
bq=2;
b=2;
}
continue;
}
if(b==2 && h2[locat2]!=0){
int t=h2[locat2];
h2[locat2]=a[i];
a[i]=t;
i--;
b=1;
continue;
}
if(b==2 && h2[locat2]==0){
h2[locat2]=a[i];
if(bq==2){
bq=2;
b=2;
}else{
bq=1;
b=1;
}
continue;
}
}
printf("Case %d:\n",cc+1);
int cou=0;
for(i=0;i<n1;i++){
if(h1[i]!=0){
cou++;
break;
}
}
if(cou!=0){
printf("Table 1\n");
for(int i=0;i<n1;i++){
if(h1[i]!=0){
printf("%d:%d\n",i,h1[i]);
}
}
}
cou=0;
for(i=0;i<n2;i++){
if(h2[i]!=0){
cou++;
break;
}
}
if(cou!=0){
printf("Table 2\n");
for(int i=0;i<n2;i++){
if(h2[i]!=0){
printf("%d:%d\n",i,h2[i]);
}
}
}
cc++;
}
return 0;
}