通用散列表

    用散列表存储数据在理论上能做到常量级的查询或插入时间复杂度。散列表中最核心的是求取哈希值。有集合R、有限整数集Z,将R映射到Z的函数称为散列函数。

    整数的散列函数可以为取模函数,因为整数域中的任何元素总可以通过取模操作被限制到一定范围内;

    字符串的散列函数有很多,不一一列举;

    结构体的散列函数则可以视结构体的具体结构而定。

    ......

    题为“通用散列表”,所以这里实现的散列表并不依赖于具体的数据类型,本实现仅提供散列表查询和插入的接口,具体的散列函数需由调用该接口的用户提供。

    参考源码:

#define MAX_SIZE 10009
#define SAME 0
#define TRUE 1
#define FALSE 0
struct HashNode
{
    void* value;
    struct HashNode* next;
};
static struct HashNode* g_hash_table[MAX_SIZE];
typedef unsigned int (*func_hash_value)(void* value);
typedef int (*func_cmp)(void*, void*);

int hash_insert_value(void* value, func_hash_value hash_value, func_cmp cmp)
{
    unsigned int val = hash_value(value) % MAX_SIZE;
    struct HashNode* p = g_hash_table[val];

    for (; p != NULL; p = p->next)
        if (cmp(p->value, value) == SAME)// the value is already insert into the table
            return 0;
    if (!(p = (struct HashNode*)malloc(sizeof(struct HashNode))))
        return -1;// insert failed
    p->value = value;
    p->next  = g_hash_table[val];
    g_hash_table[val] = p;
    return 0;
}

int hash_has_value(void* value, func_hash_value hash_value, func_cmp cmp)
{
    unsigned int val = hash_value(value) % MAX_SIZE;
    struct HashNode* p = g_hash_table[val];

    for (; p != NULL; p = p->next)
        if (cmp(p->value, value) == SAME)
            return TRUE;
    return FALSE;
}
    func_hash_value为散列函数,func_cmp比对函数。这两个函数均需由用户提供。

    下列源码提供了字符串散列表的测试例程。

unsigned int bkdr_hash_value(char *str)
{
	unsigned int seed = 131;// 31 131 1313 13131 131313 ...
	unsigned int hash = 0;

	while (*str)
		hash = hash * seed + (*str++);

	return (hash & 0x7FFFFFFF);
}

int string_cmp_func(void* a, void* b)
{
    return strcmp((char*)a, (char*)b);
}

int main(int argc, char* argv[])
{
    int n, a, i;
    char* str = NULL;
    char s[100];

    memset(g_hash_table, 0, sizeof(g_hash_table));
    scanf("%d", &n);
    while (n--)
    {
        str = (char*)malloc(100);
        scanf("%s", str);
        hash_insert_value((void*)str, (unsigned int(*)(void*))bkdr_hash_value, string_cmp_func);
    }
    printf("hash table already created. now input the times you want to search\n");
    scanf("%d", &n);
    while (n--)
    {
        scanf("%s", s);
        printf("value %s %s\n", s,
                hash_has_value((void*)s, (unsigned int(*)(void*))bkdr_hash_value, string_cmp_func) == TRUE ? "exist" : "not exit");
    }
    return 0;
}
    hash_has_value((void*)s, (unsigned int(*)(void*))bkdr_hash_value, string_cmp_func),此处可能不太好理解,” (unsigned int(*)(void*))bkdr_hash_value“是什么东西?这种用法确实不常见,但如果不在bkdr_hash_value前加那么一段可能编译就通不过,因为函数类型与所要求的并不一致,所以前面的那一段实际上是强制类型转换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值