链式hashmap实现笔记

Memcached里的Hashmap实现是一个简单的链式存储方式,简单记录一下
链式hashmap的结构比较简单,基本上可以理解为一个一维线性空间,每个空间称作一个bucket,每个bucket又是一个链表结构,这个链表结构上的所有元素的key的hash值是相同的,所以被分配在一个bucket里。

hashmap存储时首先根据key计算hash得到对应bucket,然后加入该bucket中的链表首部
hashmap查询时也是通过key计算hash得到对应bucket,然后遍历链表查找对应元素

所以hashmap的关键是hash的算法是否可以尽可能的减小不同key值计算出相同hash的概率(减小冲突),如果所有的key的hash均相同,那么hashmap也就变成了List结构了


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned long int ub4; /* unsigned 4-byte quantities */
typedef unsigned char ub1; /* unsigned 1-byte quantities */

/* hard-code one million buckets, for now (2**20 == 4MB hash) */
#define HASHPOWER 20 // 1<<20 = buckets 的总数

#define hashsize(n) ((ub4)1<<(n))
#define hashmask(n) (hashsize(n)-1) // 防止hash值超过buckets总长度

#define mix(a,b,c) \
{ \
a -= b; a -= c; a ^= (c>>13); \
b -= c; b -= a; b ^= (a<<8); \
c -= a; c -= b; c ^= (b>>13); \
a -= b; a -= c; a ^= (c>>12); \
b -= c; b -= a; b ^= (a<<16); \
c -= a; c -= b; c ^= (b>>5); \
a -= b; a -= c; a ^= (c>>3); \
b -= c; b -= a; b ^= (a<<10); \
c -= a; c -= b; c ^= (b>>15); \
}

//测试用的一个item
typedef struct _item{
struct _item *next;
char *key;
char *value;
}item;

//最重要的算法部分
ub4 hash( k, length, initval)
register ub1 *k; /* the key */
register ub4 length; /* the length of the key */
register ub4 initval; /* the previous hash, or an arbitrary value */
{
register ub4 a,b,c,len;

/* Set up the internal state */
len = length;
a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
c = initval; /* the previous hash value */

/*------------------------------------ handle most of the key*/
while (len >= 12)
{
a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
mix(a,b,c);
k += 12; len -= 12;
}

/*------------------------------------- handle the last 11 bytes*/
c += length;
switch(len) /* all the case statements fall through*/
{
case 11: c+=((ub4)k[10]<<24);
case 10: c+=((ub4)k[9]<<16);
case 9 : c+=((ub4)k[8]<<8);
/* the first byte of c is reserved for the length */
case 8 : b+=((ub4)k[7]<<24);
case 7 : b+=((ub4)k[6]<<16);
case 6 : b+=((ub4)k[5]<<8);
case 5 : b+=k[4];
case 4 : a+=((ub4)k[3]<<24);
case 3 : a+=((ub4)k[2]<<16);
case 2 : a+=((ub4)k[1]<<8);
case 1 : a+=k[0];
/* case 0: nothing left to add */
}
mix(a,b,c);
/*-------------------------------------------- report the result*/
return c;
}

static item **hashtable=0;

//初始化hash buckets空间
void assoc_init(void) {
unsigned int hash_size = hashsize(HASHPOWER) * sizeof(void*);
hashtable = malloc(hash_size);
if (! hashtable) {
fprintf(stderr, "Failed to init hashtable.\n");
exit(1);
}
memset(hashtable, 0, hash_size);
}

item *assoc_find(char *key){
ub4 hv = hash(key, strlen(key), 0) & hashmask(HASHPOWER);
item *it = hashtable[hv];
while(it){
if(strcmp(it->key,key)==0)
return it;
it=it->next;
}
return 0;
}
int assoc_insert(char *key,item *it){
ub4 hv = hash(key, strlen(key), 0) & hashmask(HASHPOWER);
it->next = hashtable[hv];
hashtable[hv] = it;
return 1;
}
int main(int argc,char **argv){
assoc_init();

item *it=malloc(sizeof(item));
it->key=malloc(200);
it->value=malloc(200);
strcpy(it->key,"k1");
strcpy(it->value,"value1");
assoc_insert("k1",it);

item *head=assoc_find("k1");

printf("%s->%s",head->key,head->value);


}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值