//二进制键值类型hash map的简单应用
#include <hash_map>
#include <iostream>
#include <string>
#include <assert.h>
using namespace std;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
//一,定义
//首先,定义键类,需要包含一个字节数组和长度字段(如果键值使用长度固定,这个字段可不用)
const int MAX_KEY_LEN = 17;//根据需要改变
typedef struct MyKey
{
public:
MyKey()
{
len = 0;
memset(keyVal, 0, MAX_KEY_LEN);
}
public:
uint8_t keyVal[MAX_KEY_LEN];
uint8_t len;
}MyKey;
//然后,定义一个hash函数,这里用到著名的SuperFastHash(http://www.azillionmonkeys.com/qed/hash.html)
//safari和chrome的webkit引擎采用的就是这个hash函数,摘录改名如下:
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
+(uint32_t)(((const uint8_t *)(d))[0]) )
uint32_t Myhash(const char * data, int len) {
uint32_t hash = len, tmp;
int rem;if (len <= 0 || data == NULL) return 0;
rem = len & 3;
len >>= 2;/* Main loop */
for (;len > 0; len--) {
hash += get16bits (data);
tmp = (get16bits (data+2) << 11) ^ hash;
hash = (hash << 16) ^ tmp;
data += 2*sizeof (uint16_t);
hash += hash >> 11;
}/* Handle end cases */
switch (rem) {
case 3: hash += get16bits (data);
hash ^= hash << 16;
hash ^= data[sizeof (uint16_t)] << 18;
hash += hash >> 11;
break;
case 2: hash += get16bits (data);
hash ^= hash << 11;
hash += hash >> 17;
break;
case 1: hash += *data;
hash ^= hash << 10;
hash += hash >> 1;
}/* Force "avalanching" of final 127 bits */
hash ^= hash << 3;
hash += hash >> 5;
hash ^= hash << 4;
hash += hash >> 17;
hash ^= hash << 25;
hash += hash >> 6;return hash;
}
//最后,定义一个等于比较函数,这里先根据长度(如上所述若键的len字段不用,这里就不用这一步),
//再用memcmp直接比较就行
struct Myequal
{
bool operator() (const MyKey &key1, const MyKey &key2) const
{
if (key1.len != key2.len)
return false;
return (0 == memcmp(key1.keyVal, key2.keyVal, key1.len));
}
};
//二,使用
//定义好hash函数和等于比较函数以后就可以定义hash_map和相应的类型,如下:
typedef hash_map <MyKey, void *, Myhash, Myequal> MyHashmap;
typedef MyHashmap::iterator MyHashmap_iterator;
typedef pair <MyKey, void *> MyHashmap_Pair;
typedef pair <MyHashmap::iterator, bool > MyHashmap_PairInsert;
int main(int argc, char* argv[])
{
MyHashmap fmap;
MyKey key;
//根据应用填充key
uint8_t someval [] = {0x12,0x34,0x56,0xab,0xcd,0xef};
key.len = sizeof(someval);
memcpy(key.keyVal,someval,key.len);
//插入
MyHashmap_Pair fpair(key, new string("hello,hash map!"));
MyHashmap_PairInsert finst = fmap.insert(fpair);
if( finst.second != true )//如果插入重复键
{
//...
return -1;
}
//查找
MyHashmap_iterator it = fmap.end();
it = fmap.find(key);
if (it == fmap.end())
{
cout<<"没找到,怎么可能!!"<<endl;
}else{
cout<<*(string *)it->second<<endl;
}
key.keyVal[0] = 0x78;
fmap.insert(make_pair(key,new string("第二个")));
key.keyVal[5] = 0x90;
fmap.insert(make_pair(key,new string("第三个")));
//遍历和删除
for (MyHashmap_iterator it = fmap.begin();it != fmap.end();)
{
std::string *v = (string*)it->second;
assert(v);
if (v->compare("第二个") == 0)
{
fmap.erase(it++);
}else{
++it;
}
}
cout<<"hash map size:"<<(int)fmap.size()<<",buckets:"<<(int)fmap.bucket_count()<<endl;
return 0;
}
浙公网安备 33010602011771号