哈希表的简单实现


     下面这个散列表的实现来自K&R,很经典。在其他场景中遇到的实现更复杂,基本原理不变,只是在hash算法,或者在快速查询上做了优化。

#include  <stdio.h>
#include  <stdlib.h>

//具有相同hash值构成的链表
struct  nlist{
     struct  nlist *  next ;
     char  *  name ;   //key-定义的名字
     char  *  defn ;   //value-替换文本
};

#define  HASHSIZE 101   //桶的大小
static   struct  nlist *hashtable[HASHSIZE];  //hash table

//字符串hash函数
unsigned  hash(  char  *s){
     unsigned  hashval;
     for (hashval = 0; s !=  '\0' ; s++)
        hashval = *s + hashval * 31;  //the seed can be 1313,131313 etc..
     return  hashval % HASHSIZE;
}

//查找函数,在 hashtable中找字符串s所在的bucket
struct  nlist *lookup(  char  *s){
     struct  nlist *np;
     for (np = hashtable[hash(s)]; np; np = np->  next )
         if  (strcmp(s, np-> name  ) == 0)
             return  np;
     return  NULL;
}

//加入函数,将(name, defn)加入到 hashtable中,如果已经存在则更新
//如果无足够空间申请表项则返回空
struct  nlist *install(  char  *name,  char  *defn){
     struct  nlist *np;
     unsigned  hashval;
     if ((np = lookup(name)) == NULL){  //要插入的key不存在
        np = (  struct  nlist *)malloc(  sizeof (  struct  nlist));
         if  (np == NULL || (np->  name  = strdup(name)) == NULL)
             return  NULL;
        hashval = hash(name);
         //放入相应的桶中
        np->  next  = hashtable[hashval];
        hashtable[hashval] = np;
    }  else //已存在,则更新
        free((  void  *)np-> defn  );
    }
     //最后统一处理 value
     if ((np->  defn  = strdup(defn) ) == NULL)
         return  NULL;
     return  np;
}

//从哈希表中删除一个key-value
void  undef(  char  *s){
     unsigned  h;
     struct  nlist *prev, *np;

    prev = NULL;
    h = hash(s);
     for (np = hashtable[h]; np != NULL; np = np->  next ){
         if  (strcmp(s, np-> name  ) == 0)
             break   //找到相应的结点
        prev = np;  // 保留目标结点的前一个结点
    }

     if (np != NULL){
         if  (prev == NULL //说明要删除的是桶的第一个成员
            hashtable[h] = np->  next ;
         else
            prev->  next  = np->  next ;
        free((  void  *)np-> name  );  //切记要分别释放
        free((  void  *)np-> defn  );
        free((  void  *)np);
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值