C算法精解-----哈希表(1)

  前面写过一篇哈希表在检索SIP电话中的应用,是在阅读代码中遇到的,而专门去学习了哈希表的基本思想和哈希函数。下面自己阅读C算法精解书籍中自己总结了下面的内容。只总结一小部分,随后会继续更新。现在也在学习思维导图的应用,前面的博客中已经使用过。下面就利用思维导图总结的哈希表的内容:

 

    下面介绍个经典的字符串哈希函数:

/*hashpjw.c*/

unsigned int hashpjw(const void *key)
{
    const char *ptr;
    unsigned int val;

    val = 0;
    ptr = key;
    while (*ptr != '\0'){
        unsigned int tmp;
        val = (val << 4) +(*ptr);
        if (tmp = (val & 0xf0000000)){
            val = val ^ (tmp >> 24);
            val = val ^ tmp;
        }
        ptr++;
    }
    return val%PRIME_TBLSIZ //桶的个数
}

链式哈希表构造图

 

链式哈希表的实现和定义

/*chtbl.h*/

#ifndef CHTBL_H
#define CHTBL_H

#include <stdlib.h>
/*单链表的头文件*/
#include "list.h"

/* 定义一个链式哈希表的结构体*/

typedef struct Chtbl_ {
    int buckets; /*哈希表分配桶的个数*/
    int (*h)(const void *key);/*哈希函数指针h */
    int (*match)(const void *key1,const void *key2);/*判断2个键是否匹配*/
    void (*destroy)(void *data);/*释放内存空间*/

    int size;/*成员个数*/
    List *table;/*哈希表中链表桶的头指针*/
}Chtbl;

/* 函数接口*/
int  chtbl_init (Chtbl *htbl,int buckets,int (*h)(const void *key),int 
(*match)(const void *key1,const void *key2),void (*destroy)(void *data));
int chtbl_destroy (Chtbl *htbl);
int chtbl_insert(Chtbl *htbl,const void *data);
int chtbl_remove (Chtbl *htbl,void **data);
int chtbl_lookup(const Chtbl *htbl,void **data);

#define chtbl_size(Chtbl *htbl) ((htbl)->size)

#endif
        
/*chtbl_c*/
#include <stdlib.h>
#include <string.h>

#include "./include/list.h"
#include "./include/chtbl.h"

/* 初始化哈希表结构体*/
int chtbl_init(Chtbl * htbl, int buckets, int(* h)(const void * key), int(* match)(const void * key1, const void * key2), void(* destroy)(void * data))
{
    int i;
    /* 申请空间为桶*/
    if ((htbl->table = (List *)malloc(buckets * sizeof(List))) == NULL){
        return -1;
    }
    /* 初始化哈希表*/
    htbl->buckets = buckets;
    for (i = 0; i < buckets; i++){
        list_init(&htbl->table[i], destroy);
    }
    htbl->h = h;
    htbl->match = match;
    htbl->destroy = destroy;
    htbl->size = 0;
    return 0;

}

/*哈希表销毁*/
void chtbl_destroy(Chtbl * htbl)
{
    int i;
    if (htbl == NULL)
        return;
    /*销毁各个桶*/
    for (i = 0; i < htbl->buckets; i++){
        list_destory(htbl->table[i]);
    }

    /* 释放hash table 空间*/
    free(htbl->table);

    /*清空htbl结构体*/
    memset(htbl,0,sizeof(Chtbl));
    return ;
    
}
/* 插入数据
 * return 成功返回0;失败返回-1;存在返回1;
 *
 */
int chtbl_insert(Chtbl * htbl, const void * data)
{
    void *temp;
    int bucket;
    int retval;

    /*如何data已经在哈希表中返回1*/
    temp = (void *)data;
    if (chtbl_lookup(htbl, &temp) == 0)
        return 1;
    /*获得哈希键*/
    bucket = htbl ->h(data) % htbl->buckets;
    /*插入哈希表*/
    if ((retval = list_ins_next(htbl->table[bucket], NULL, data)) == 0)
        htbl ->size ++;
    return retval;
}

/*删除数据
  *return 成功返回0;失败返回-1;
  */
int chtbl_remove(Chtbl * htbl, void * * data)
{
    ListElmt *element = NULL;
    ListElmt *prev = NULL;
    int bucket = -1;

    /*获得哈希键*/
    bucket = htbl ->h(*data)%htbl -> buckets;
    /*查找在哈希表中的data*/
    for (element = list_head(&htbl->table [bucket]);element != NULL;element = 
    list_next(element)){
        if (htbl->match(*data,list_data(element))){
            if (list_rem_next(&htbl->table[bucket], prev, data) == 0){
                htbl->size --;
                return 0;
            } else {
                return -1;
            }
        }
        prev = element;
    }
    return -1;
}

/* 在哈希表中查找元素
  *return :如果找到元素返回0;否则返回-1.
  */
int chtbl_lookup(const Chtbl * htbl, void * * data)
{
    ListElmt *element;
    int bucket;

    /*获得哈希键*/
    bucket = htbl -> h(*data)%htbl->buckets;
    /*在哈希表中查找元素*/
   for (element = list_head(&htbl->table [bucket]);element != NULL;element = 
    list_next(element)){
        if (htbl->match(*data,list_data(element))){
            
*data = list_data(element);
           return 0;
        }
    }
   return -1;
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值