`
bachmozart
  • 浏览: 111371 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

链式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);


}

分享到:
评论
2 楼 mathgl 2009-02-25  
bucket那种形式貌似好实现一些
1 楼 kimmking 2009-02-24  
java里的hashmap是用的链式
.net里的hashtable(等价于java的hashmap)用的是二次hash

相关推荐

    java精华学习笔记

    - **Map**: 存储键值对的数据结构,如HashMap和TreeMap。 - **泛型**: 提高代码安全性,限制集合只能存储特定类型的对象。 5. **输入输出流** - 文件I/O:使用FileReader/Writer处理文本文件,FileInputStream/...

    java 培训笔记与代码

    - **HashSet与HashMap**:存储无序不重复元素,HashSet基于哈希表,HashMap存储键值对,查找效率高。 - **TreeSet与TreeMap**:基于红黑树的数据结构,保证元素排序。 5. **IO流** - **流的概念**:Java的IO流...

    JUC学习笔记(Java多线程)

    最后,`CompletableFuture`是Java 8引入的异步编程工具,它提供了链式调用、组合多个异步操作的能力,极大地简化了复杂异步逻辑的编写。 总的来说,JUC学习笔记涵盖了Java多线程编程的主要方面,包括线程的创建与...

    Java笔记.zip

    - **容器**:如ArrayList、LinkedList、HashSet、HashMap等,用于存储和管理对象。 - **迭代器**:遍历集合的接口,提供了add、remove和hasNext等方法。 - **泛型**:在定义集合时指定元素类型,避免类型转换并...

    JAVA学习Java集合框架.pptx

    LinkedList是List的实现类,提供了链式存储方式。LinkedList可以用于存储大量数据,并提供了高效率的插入和删除操作。 HashMap的使用 HashMap是Map的实现类,提供了键值对的存储方式。HashMap可以用于存储大量数据...

    JAVA笔记总结

    10. **多线程**:Java提供了Thread类和Runnable接口来实现并发执行,还包括同步机制(synchronized关键字、wait()、notify()、notifyAll()方法)。 11. **网络编程**:Socket编程,用于创建客户端和服务器之间的...

    Java架构面试专题汇总(含答案)和学习笔记.zip

    - List、Set、Map接口及其实现类的特性与用法,如ArrayList、LinkedList、HashSet、HashMap等。 - 集合操作:迭代器、泛型、并发集合(CopyOnWriteArrayList、ConcurrentHashMap)等。 - 并发容器:如...

    java内部学习笔记.docx

    20. Map集合的实现类HashMap:键值对存储,键唯一。 21. 单例模式和模板方法模式:设计模式,解决特定问题。 22. Java异常处理机制:try-catch-finally、throw、throws关键字,处理程序中的错误。 23. File类:文件...

    Effective-Java读书笔记(上)

    ### Effective Java读书笔记(上) #### 第一章 引言 本书主要针对Java开发者提供了大量实用的编程指导建议,帮助读者提升代码质量和程序性能。在本章节中,我们将重点介绍对象的创建与销毁,以及一些重要的设计...

    Java高级程序设计课程大作业.zip

    深入理解它们的特性和使用场景,例如ArrayList的快速随机访问,LinkedList的链式结构适合插入删除操作,以及HashMap的散列原理。 3. **IO与NIO**:Java I/O流处理是基础,涉及FileInputStream、OutputStream等类,...

    LeetCode:LeetCode刷题记录

    - **哈希表**:用HashMap和LinkedHashMap实现,LeetCode中常用于查找和存储元素。 - **二叉树**:自定义节点类,如`data class TreeNode(var val: Int, var left: TreeNode? = null, var right: TreeNode? = null)...

    bharris4.github.io:CS 161 COCC

    6. **集合框架**:Java集合框架包括List、Set、Queue和Map接口,以及ArrayList、LinkedList、HashSet、HashMap等实现类。这些容器用于存储和管理对象。 7. **输入/输出(I/O)**:学习使用File类、Scanner类进行文件...

Global site tag (gtag.js) - Google Analytics