c语言 ---- HashMap实现

来源:互联网 发布:java url encoder 编辑:程序博客网 时间:2024/05/02 19:20

   c语言中,关于类似HashTable的实现;

优点:检索/插入/删除高效率;

注意:可存储任意类型的指针(非值存储)

/*************************************************************************

    > File Name: shashmap.h
    > Author: tangzs
    > Mail: 21349338@qq.com
    > Created Time: 2017年09月18日 星期一 22时58分01秒
 ************************************************************************/
#ifndef ____SHASHMAP_H____
#define ____SHASHMAP_H____


/*
 * 求 int 型哈希值
 */
extern unsigned int hashcode_int(void *key);

/*
 * int 型指针比较
 */
extern int equals_int(void *key1, void *key2);

/*
 * 求 string 型哈系值
 */
extern unsigned int hashcode_str(void *key);

/*
 * string 型比较
 */
extern int equals_str(void *key1, void *key2);

/*
 * 哈希表节点结构定义
 */
typedef struct st_entry {
    
    void *key;    // key
    void *val;    // val
    struct st_entry *next; // 解决冲突/列表方式
} Entry;

/*
 * 哈希表结构定义
 */
typedef struct {

    int size;    // 当前有效大小
    int table_size;    // 哈系表数组大小
    Entry *table_array;    // 哈系表数组
    unsigned int (*hashcode)(void *key); // 键值哈希值函数
    int (*equals)(void *key1, void *key2); // 键比较函数
} SHashMap;

/*
 * 哈希表创建及初始化
 */
extern SHashMap *shashmap_init(unsigned int (*hashcode)(void *key),
        int (*equals)(void *key1, void *key2));

/*
 * 向哈希表添加键值对
 */
extern void shashmap_put(SHashMap *map, void *key, void *val);

/*
 * 根据键获取值
 */
extern void *shashmap_get(SHashMap *map, void *key);

/*
 * 销毁哈希表
 */
extern void shashmap_free(SHashMap *map);

#endif


/*************************************************************************
    > File Name: shashmap.c
    > Author: tangzs
    > Mail: 21349338@qq.com
    > Created Time: 2017年09月18日 星期一 23时02分45秒
 ************************************************************************/
#include "shashmap.h"

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

extern unsigned int hashcode_int(void *key) {
    int k = *(int*)key;
    return k < 0? 131 - k: 131 + k;
}

extern int equals_int(void *key1, void *key2) {
    int k1 = *(int*)key1;
    int k2 = *(int*)key2;
    return k1 == k2? 1: 0;
}

extern unsigned int hashcode_str(void *key) {
    
    unsigned int hashcode = 0;
    char *str = (char*)key;
    while (*str) {
        hashcode = (*str++) + (hashcode << 6) + (hashcode << 16) - hashcode;
    }
    hashcode &= 0x7FFFFFFF;
    return hashcode;
}

extern int equals_str(void *key1, void *key2) {
    char *k1 = (char*)key1;
    char *k2 = (char*)key2;
    while (1) {
        if (*k1 != *k2) {
            return 0;
        }
        if (*k1) {
            break;
        }
    }
    return 1;
}

extern SHashMap *shashmap_init(unsigned int (*hashcode)(void *key),
        int (*equals)(void *key1, void *key2)) {

    SHashMap *map = malloc(sizeof(SHashMap));
    if (map == NULL) {
        perror("malloc shashmap error");
        exit(0);
    }
    map->hashcode = hashcode;
    map->equals = equals;
    map->size = 0;
    map->table_size = 131;
    map->table_array = calloc(map->table_size, sizeof(Entry));
    if (map->table_array == NULL) {
        perror("calloc shashmap table array error");
        exit(0);
    }
    return map;
}

extern void shashmap_put(SHashMap *map, void *key, void *val) {

    int index = (*(map->hashcode))(key) % map->table_size;
    Entry *table = map->table_array + index;
    Entry *entry = malloc(sizeof(Entry));
    if (entry == NULL) {
        perror("malloc entry error");
        exit(0);
    }
    entry->key = key;
    entry->val = val;
    entry->next = table->next;
    table->next = entry;
}

extern void *shashmap_get(SHashMap *map, void *key) {

    int index = (*(map->hashcode))(key) % map->table_size;
    Entry *entry = (map->table_array + index)->next;
    while (entry != NULL) {
        int v =  ((*map->equals)(key, entry->key));
        if ((*map->equals)(key, entry->key)) {
            return entry->val;
        }
        entry = entry->next;
    }
    return NULL;
}

extern void shashmap_free(SHashMap *map) {

    for (int i = 0; i < map->table_size; i++) {
        Entry *entry = (map->table_array + i)->next;
        while (entry != NULL) {
            Entry *temp = entry;
            entry = entry->next;
            free(temp);
        }
    }
    free(map->table_array);
    free(map);
}

原创粉丝点击