一、哈希表
哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
记录的存储位置=f(关键字)
这里的对应关系f称为散列函数,又称为哈希(Hash函数),采用散列技术将记录存储在一块连续的存储空间中,这块连续存储空间称为散列表或哈希表(Hash table)。
各类hash函数性能总结:https://blog.csdn.net/qigaohua/article/details/102838234
哈希表hashtable(key,value) 就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里。(或者:把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。) 而当使用哈希表进行查询的时候,就是再次使用哈希函数将key转换为对应的数组下标,并定位到该空间获取value,如此一来,就可以充分利用到数组的定位性能进行数据定位。
二、代码实现
hashmap.h
#ifndef __HASH_MAP__
#define __HASH_MAP__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define HASH_MAP_SIZE 100
typedef int DATA;
typedef int (*func)(DATA, DATA);
typedef struct _hashNode {
char *key;
DATA data;
struct _hashNode *next;
}hashNode_s, *hashNode_p;
//struct _hashNode* hashMap[HASH_MAP_SIZE];
int createHashMap(hashNode_s **hashMap);
int destroyHashMap(hashNode_s **hashMap);
hashNode_p lookupHashMap(char *key, hashNode_s **hashMap);
int insertHashValue(char *key, DATA data, hashNode_s **hashMap);
#endif
hashmap.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include "hashmap.h"
hashNode_s *clamscam[HASH_MAP_SIZE];
int crateHashMap(hashNode_s **hashMap)
{
int i;
for (i = 0; i < HASH_MAP_SIZE; i ++) {
hashMap[i] = NULL;
}
return 0;
}
int destroyHashMap(hashNode_s **hashMap)
{
int i;
hashNode_p np, nt;
for(i = 0; i < HASH_MAP_SIZE; i++){
if (hashMap[i] != NULL) {
for(np = hashMap[i]; np != NULL; ){
nt = np->next;
free(np->key);
free(np);
np = NULL;
np = nt;
}
}
}
return 0;
}
unsigned int BKDRHash(char *str)
{
unsigned int seed = 131; // 31 131 1313 13131 131313 etc..
unsigned int hash = 0;
while (*str)
{
hash = hash * seed + (*str++);
}
return (hash & 0x7FFFFFFF) % HASH_MAP_SIZE;
}
hashNode_p lookupHashMap(char *key, hashNode_s **hashMap)
{
unsigned int hash;
hashNode_p np;
hash = BKDRHash(key);
np = hashMap[hash];
while(np) {
if (strcmp(np->key, key) == 0) {
return np;
}
np = np->next;
}
return NULL;
}
int insertHashValue(char *key, DATA data, hashNode_s **hashMap)
{
unsigned int hash;
hashNode_p np;
if (NULL != lookupHashMap(key, hashMap))
return 1;
hash = BKDRHash(key);
np = (hashNode_p)malloc(sizeof(hashNode_s));
if (NULL == np)
return -1;
np->key = key;
np->data = data;
if (hashMap[hash] == NULL) {
np->next = NULL;
hashMap[hash] = np;
}
else {
np->next = hashMap[hash];
hashMap[hash] = np;
}
return 0;
}
#if 1
/*获取任意长度的随机字符串*/
char* genRandomString(int length)
{
int flag, i;
char* string;
srand((unsigned) time(NULL ));
if ((string = (char*) malloc(length + 1)) == NULL )
{
return NULL ;
}
for (i = 0; i < length; i++)
{
flag = rand() % 3;
switch (flag)
{
case 0:
string[i] = 'A' + rand() % 26;
break;
case 1:
string[i] = 'a' + rand() % 26;
break;
case 2:
string[i] = '0' + rand() % 10;
break;
default:
string[i] = 'x';
break;
}
}
string[length] = '\0';
return string;
}
int main()
{
hashNode_p np;
char *str;
int i;
crateHashMap(clamscam);
for (i = 0; i < 100; i++) {
str = genRandomString(16);
insertHashValue(str, i, clamscam);
if ((np = lookupHashMap(str, clamscam)) != NULL)
printf("%s: %d\n",str, np->data);
else
printf("%s: no\n", str);
//free(str);
sleep(1);
}
destroyHashMap(clamscam);
return 0;
}
#endif
测试已OK。
关注公众号"小败日记",搬砖过程遇到的问题,大家一起探讨,资源共享