所谓的哈希表-散列方法就是一个结构体数组,一般的数组下表是012345,要找数据只能通过遍历;
哈希的数组也是012345,但是这个下标号是通过key值换算得来的(这个映射函数叫做散列函数,存放记录的数组叫做散列表。)。
通过key值换算成数组下标号,不需要遍历,直接找到数据;
下面是网上的一个c语言实现,比较简单,容易理解。
#ifndef _HASH_TABLE_H
#define _HASH_TABLE_H
#include <stdlib.h>
#include <memory.h>
#include <stdio.h>
#include <string.h>
#define HASH_TABLE_CAPACITY 20
typedef unsigned int uint;
/** hash table element*/
typedef struct _htItem{
struct _htItem *next;// 指向下一个的指针
char *key_string;// key
uint fid;// 记录值
} htItem;
/** init the hashTable 构造函数,申请哈希表的空间*/
void htInit(htItem **ht, uint length);
/** set hashTable element 哈希表中插入一个值*/
uint htSet(char *key, uint val, htItem **ht);
/** get element from hashtable 从哈希表中获得一个对应的key*/
htItem* htGet(char *key, htItem **ht);
/** Delete element from hashTable 从哈希表中删除一个key*/
int htDel(char *key, htItem **ht);
/** BKDR hash function 对string进行散列得到一个整数值*/
uint bkdrHash(char *key);
/** get the index of hash table 根据key计算一个整数值,然后获得对应的槽位*/
uint htIndex(char *key, htItem **ht);
/** get hashTable elements */
uint htLen(htItem **ht);
/*打印哈希表*/
void print_hashTable(htItem **ht);
#endif
#include <stdlib.h>
#include <stdio.h>
#include "hash.h"
/**************************************************************************************************
** 哈希表的类型是对一个string进行散列。
** 本哈希表使用的是开散列的办法,首先是一个指针数组,数组第一个位置中保存着哈希表的大小。
** 首先对string散列获得一个整数值,然后根据哈希表的大小计算所属的槽位,
** 然后再该槽位的链表上进行查找,如果找到则更新哈希值,如果未找到则在尾端插入。
**************************************************************************************************/
/*初始化HashTable*/
void htInit(htItem **ht, uint length){
int i;
for (i = 0; i<length; i++){
ht[i] = (htItem*)malloc(sizeof(htItem));
memset(ht[i], 0, sizeof(htItem));
}
ht[0]->fid = length;/*数组第一个位置中保存着哈希表的大小*/
}
/** get hashTable elements 进行对应的hash值的搜索,如果找到则返回该节点*/
htItem* htGet(char *key, htItem **ht){
uint i = htIndex(key, ht);
htItem *item = ht[i]->next;
htItem *tmp = (htItem*)malloc(sizeof(htItem));
memset(tmp, 0, sizeof(htItem));
printf("htGet key = %s, index = %d\n",key,i);
while (item)
{
if (strcmp(key, item->key_string) == 0){
return item;
}
item = item->next;
}
return NULL;
}
/** set hashTable element 插入新的hash值*/
uint htSet(char *key, uint fid, htItem **ht){
uint i = htIndex(key, ht);
htItem *item = ht[i];
printf("htSet key = %s, index = %d\n",key,i);
while (item->next)
{
/*已经存在的话则直接更新值*/
if (strcmp(key, item->next->key_string) == 0){
item->next->fid = fid;
return 0;
}
else{
item = item->next;
}
}
item->next = (htItem*)malloc(sizeof(htItem));
item->next->fid = fid;
item->next->key_string = key;
item->next->next = NULL;
return 0;
}
/** delete one element of hashtable 删除hash值*/
int htDel(char *key, htItem **ht){
uint i = htIndex(key, ht);
htItem *item = ht[i];
printf("htDel key = %s, index = %d\n",key,i);
while (item->next){
if (strcmp(key, item->next->key_string) == 0){
htItem *tmp = item->next;
item->next = tmp->next;
free(tmp);
return 0;
}
item = item->next;
}
return -1;
}
/** BKDR hash function 对字符串进行散列,得到一个整数的hash值*/
uint bkdrHash(char *key)
{
uint seed = 131;
uint hash = 0;
int iRet = 0;
while (*key != '\n' && *key != 0)
{
hash = hash * seed + (*key++);
printf("bkdrHash:while key %s,tmp hash %d\n",key,hash);
}
iRet = (hash & 0x7FFFFFFF);
printf("bkdrHash:key %s,hash %d,iRet %d\n",key,hash,iRet);
return iRet;
}
/** get the index of hash table 根据得到的hash值选择一个槽位置*/
uint htIndex(char *key, htItem **ht){
int iRet = 0;
uint hashedKey = bkdrHash(key);
uint length = (ht[0]->fid - 1);
iRet = (uint)hashedKey % length + 1;
printf("htIndex:key %s,iRet %d\n",key,iRet);
return iRet;
}
/** get element number in the hashtable */
uint htLen(htItem **ht){
uint alength = ht[0]->fid;
uint i, length = 0;
for (i = 1; i < alength; i++){
if (ht[i]->next) {
length++;
}
}
return length;
}
/** get capacity of hashtable */
uint htCapacity(htItem **ht)
{
return ht[0]->fid;
}
void print_hashTable(htItem **ht)
{
uint length = ht[0]->fid;
uint i;
htItem *item;
printf("\n============ Printf all table =============\n");
for (i = 1; i < length; i++)
{
item = ht[i]->next;
while (item)
{
printf("all %s => fid = %d, index = %d\n", item->key_string, item->fid, i);
item = item->next;
}
}
printf("================= End ==================\n\n");
}
int main()
{
htItem *item[101];
htInit(item, 101);
htSet("aaa", 100, item);
htSet("bbb", 1000, item);
htSet("ccc", 99, item);
htSet("ddd1", 199, item);
htSet("ddd2", 299, item);
htSet("ddd3", 399, item);
htSet("ddd4", 499, item);
htSet("ddd5", 599, item);
htSet("ddd6", 699, item);
htSet("ddd7", 799, item);
htSet("ddd8", 899, item);
htSet("ddd9", 999, item);
htSet("ddd10", 1099, item);
htSet("ddd11", 1199, item);
htSet("ddd12", 1299, item);
htSet("ddd13", 1399, item);
print_hashTable(item);
htItem *tmp = htGet("aaa", item);
htItem *tmp1 = htGet("bbb", item);
htItem *tmp2 = htGet("ccc", item);
printf("\nGeting aaa,bbb,ccc...\n");
printf("tmp1: Key %s => %d\n", tmp->key_string, tmp->fid);
printf("tmp2: Key %s => %d\n", tmp1->key_string, tmp1->fid);
printf("tmp3: Key %s => %d\n", tmp2->key_string, tmp2->fid);
printf("\nDelete bbb ...\n");
htDel("bbb", item);
print_hashTable(item);
htItem *tmp3 = htGet("bbb", item);
printf("tmp3 pointer:%u\n", tmp3);
if (tmp3) {
printf("Key %s => %d\n", tmp3->key_string, tmp3->fid);
}
}