Cuckoo Hash 布谷鸟哈希

1. 定义: 

一种解决hash冲突的方法,其目的是使用简单的hash 函数来提高hash table的利用率,同时保证O(1)的查询时间。基本思想是使用2个hash函数来处理碰撞,从而每个key都对应到2个位置。

2. 操作:

1. 对key值hash,生成两个hash key值,hashk1和 hashk2, 如果对应的两个位置上有一个为空,那么直接把key插入即可。

2. 否则,任选一个位置,把key值插入,把已经在那个位置的key值踢出来。

3. 被踢出来的key值,需要重新插入,直到没有key被踢出为止。

4. 衍生背景:

Cuckoo中文名叫布谷鸟,这种鸟有一种即狡猾又贪婪的习性,它不肯自己筑巢, 而是把蛋下到别的鸟巢里,而且它的幼鸟又会比别的鸟早出生,布谷幼鸟天生有一种残忍的动作,幼鸟会拼命把未出生的其它鸟蛋挤出窝巢,今后以便独享“养父 母”的食物。借助生物学上这一典故,cuckoo hashing处理碰撞的方法,就是把原来占用位置的这个元素踢走,不过被踢出去的元素还要比鸟蛋幸运,因为它还有一个备用位置可以安置,如果备用位置上 还有人,再把它踢走,如此往复。直到被踢的次数达到一个上限,才确认哈希表已满,并执行rehash操作。

cuckoo_preview

5. 哈希碰撞之前的空间利用率, 1维和一般hash一样为50%, 二维情况看下面例子。一个改进的哈希表如下图所示,每个桶(bucket)有4路槽位(slot)。当哈希函数映射到同一个bucket中,在其它三路slot未被填满 之前,是不会有元素被踢的,这大大缓冲了碰撞的几率。笔者自己的简单实现上测过,采用二维哈希表(4路slot)大约80%的占用率(CMU论文数据据说 达到90%以上,应该是扩大了slot关联数目所致)

cuckoo hashing

以下是一个简单的C++实现Cuckoo Hash的示例代码: ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; const int TABLE_SIZE = 11; const int MAX_RETRIES = 500; class CuckooHash { private: vector<int> table1; vector<int> table2; public: CuckooHash() { table1.resize(TABLE_SIZE); table2.resize(TABLE_SIZE); } int hash1(int key) { return key % TABLE_SIZE; } int hash2(int key) { return (key / TABLE_SIZE) % TABLE_SIZE; } void insert(int key) { int count = 0; while (count < MAX_RETRIES) { int index1 = hash1(key); int index2 = hash2(key); if (table1[index1] == key || table2[index2] == key) { cout << key << " already exists." << endl; return; } if (table1[index1] == 0) { table1[index1] = key; return; } else if (table2[index2] == 0) { table2[index2] = key; return; } else { int evictedKey = table1[index1]; table1[index1] = key; key = table2[index2]; table2[index2] = evictedKey; count++; } } cout << "Insertion failed." << endl; } void remove(int key) { int index1 = hash1(key); int index2 = hash2(key); if (table1[index1] == key) { table1[index1] = 0; } else if (table2[index2] == key) { table2[index2] = 0; } else { cout << key << " does not exist." << endl; } } bool search(int key) { int index1 = hash1(key); int index2 = hash2(key); return table1[index1] == key || table2[index2] == key; } }; int main() { CuckooHash hash; hash.insert(10); hash.insert(22); hash.insert(37); hash.insert(40); hash.insert(50); hash.insert(60); hash.remove(22); hash.remove(40); hash.insert(70); hash.insert(80); cout << "Search for 10: " << (hash.search(10) ? "Found" : "Not Found") << endl; cout << "Search for 37: " << (hash.search(37) ? "Found" : "Not Found") << endl; cout << "Search for 50: " << (hash.search(50) ? "Found" : "Not Found") << endl; cout << "Search for 80: " << (hash.search(80) ? "Found" : "Not Found") << endl; cout << "Search for 90: " << (hash.search(90) ? "Found" : "Not Found") << endl; return 0; } ``` 代码中使用了两个哈希表作为Cuckoo Hash的基础数据结构,其中使用了两个不同的哈希函数来计算每个键的两个哈希值。在插入键时,如果一个键已经存在于两个哈希表中的任何一个中,则插入操作失败。如果两个哈希表中有一个空闲位置,则将键插入其中一个哈希表中。如果两个哈希表中都没有空闲位置,则使用Cuckoo Hash算法将其中一个哈希表中的键替换为新插入的键,同时将被替换的键移动到另一个哈希表中。在删除键时,如果一个键存在于哈希表中,则将其从哈希表中删除。在搜索键时,如果一个键存在于两个哈希表中的任何一个中,则返回true,否则返回false。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值