目录
- 一.引入
- 二.哈希表结构
- 三.SDBMHash算法(字符->数字)★
- 四.哈希表的算法实现
- 1.哈希函数
- 2.初始化
- 3.查找
- 4.插入
- 5.删除
- 6.获取数据
- 7.销毁
- 五.完整代码
- 1.头文件
- 2.源文件
- 3.运行结果
一.引入
原来我们讲的都是以整数作为关键码,那么我们可不可以用字符串来作为关键码呢?
有的时候我们希望能够很快的查找字符串.
那么如果我们也想用哈希表存储,我们该怎么办呢?
答案是基本思想还是不变,哈希函数求余来进行分组.
但是字符串怎么可能求取呢?
那么就需要我们进行转换了,就是大名鼎鼎的SDBM算法
二.哈希表结构
跟原来一样,只不过关键码的类型不在是整型了,c++中的字符串是const char*,所以这里用的const void*.
三.SDBMHash算法(字符->数字)★
可以将不同的字符串转换成为不同的数字,就方便我们进行取余分组了.
四.哈希表的算法实现
1.哈希函数
先将字符串转换为数字再取余进行操作.
2.初始化
HashTable* initHash(int TableSize)
{
int i = 0;
HashTable* hTable = NULL;
if (TableSize <= 0)
{
TableSize = DEFAULT_SIZE;
}
hTable = (HashTable*)malloc(sizeof(HashTable));
if (NULL == hTable)
{
printf("HashTable malloc error.\n");
return NULL;
}
hTable->TableSize = TableSize;
hTable->Thelists = (List*)malloc(sizeof(List) * TableSize);
if (hTable->Thelists == NULL)
{
printf("HashTable malloc error\n");
free(hTable);
return NULL;
}
for (i = 0; i < hTable->TableSize; i++)
{
hTable->Thelists[i] = (ListNode*)malloc(sizeof(ListNode));
if (NULL == hTable->Thelists[i])
{
printf("HashTable malloc error\n");
free(hTable->Thelists);
free(hTable);
return NULL;
}
else
{
memset(hTable->Thelists[i], 0, sizeof(ListNode));
}
}
return hTable;
}
3.查找
4.插入
void insert(HashTable* HashTable, const void* key, const void* value)
{
Element e = NULL, tmp = NULL;
List L = NULL;
e = Find(HashTable, key);
if (e == NULL)
{
tmp = (Element)malloc(sizeof(ListNode));
if (tmp == NULL)
{
printf("malloc error\n");
return;
}
int code = Hash(key, HashTable->TableSize);
L = HashTable->Thelists[code];
tmp->data = value;
tmp->key = key;
tmp->next = L->next;
L->next = tmp;
}
else
{
printf("the key already exist\n");
}
}
5.删除
6.获取数据
7.销毁
这是关键码的类型改变了一下,其他都一样,就不讲了.
五.完整代码
1.头文件
#pragma once
#define DEFAULT_SIZE 16
typedef struct _ListNode
{
struct _ListNode* next;
const void* key;
const void* data;
}ListNode;
typedef ListNode* List;
typedef ListNode* Element;
typedef struct _HashTable
{
int TableSize;
List* Thelists;
}HashTable;
2.源文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hash_table.h"
#define BUCKET_SIZE 1024
#define compare(a,b) strcmp((const char*)a,(const char*)b)
#define hash_func SDBMHash
unsigned int SDBMHash(const void* key)
{
unsigned int hash = 0;
char* str = (char*)key;
while (*str)
{
hash = (*str++) + (hash << 6) + (hash << 16) - hash;
}
return (hash & 0x7FFFFFFF);
}
int Hash(const void* key, int TableSize)
{
return hash_func(key) % TableSize;
}
HashTable* initHash(int TableSize)
{
int i = 0;
HashTable* hTable = NULL;
if (TableSize <= 0)
{
TableSize = DEFAULT_SIZE;
}
hTable = (HashTable*)malloc(sizeof(HashTable));
if (NULL == hTable)
{
printf("HashTable malloc error.\n");
return NULL;
}
hTable->TableSize = TableSize;
hTable->Thelists = (List*)malloc(sizeof(List) * TableSize);
if (hTable->Thelists == NULL)
{
printf("HashTable malloc error\n");
free(hTable);
return NULL;
}
for (i = 0; i < hTable->TableSize; i++)
{
hTable->Thelists[i] = (ListNode*)malloc(sizeof(ListNode));
if (NULL == hTable->Thelists[i])
{
printf("HashTable malloc error\n");
free(hTable->Thelists);
free(hTable);
return NULL;
}
else
{
memset(hTable->Thelists[i], 0, sizeof(ListNode));
}
}
return hTable;
}
Element Find(HashTable* HashTable, const void* key)
{
int i = 0;
List L = NULL;
Element e = NULL;
i = Hash(key, HashTable->TableSize);
L = HashTable->Thelists[i];
e = L->next;
while (e!=NULL&&compare(e->key,key)!=0)
{
e = e->next;
}
return e;
}
void insert(HashTable* HashTable, const void* key, const void* value)
{
Element e = NULL, tmp = NULL;
List L = NULL;
e = Find(HashTable, key);
if (e == NULL)
{
tmp = (Element)malloc(sizeof(ListNode));
if (tmp == NULL)
{
printf("malloc error\n");
return;
}
int code = Hash(key, HashTable->TableSize);
L = HashTable->Thelists[code];
tmp->data = value;
tmp->key = key;
tmp->next = L->next;
L->next = tmp;
}
else
{
printf("the key already exist\n");
}
}
void Delete(HashTable* HashTable, void* key)
{
Element e = NULL, last = NULL;
List L = NULL;
int i = Hash(key, HashTable->TableSize);
L = HashTable->Thelists[i];
e = L->next;
while (e!=NULL&&e->key!=key)
{
last = e;
e = e->next;
}
if (e)
{
last->next = e->next;
free(e);
}
}
const void* Retrieve(Element e)
{
return e ? e->data : NULL;
}
void Destory(HashTable* HashTable)
{
int i = 0;
List L = NULL;
Element cur = NULL, next = NULL;
for (i = 0; i < HashTable->TableSize; i++)
{
L = HashTable->Thelists[i];
cur = L->next;
while (cur!=NULL)
{
next = cur->next;
free(cur);
cur = next;
}
free(L);
}
free(HashTable->Thelists);
free(HashTable);
}
void main(void)
{
const char* elems[] = { "ADBB","BDDC","CDBC","BDBB" };
const char* tester = "ABDBBBAC";
char cur[5] = { '\0' };
HashTable* HashTable = NULL;
HashTable = initHash(BUCKET_SIZE);
for (int i = 0; i < sizeof(elems) / sizeof(elems[0]); i++)
{
insert(HashTable, elems[i], elems[i]);
}
strncpy_s(cur, tester + 1, 4);//BDBB'\0'
Element e = Find(HashTable, cur);
if (e)
{
printf("存在基因片段:%s 为色盲!\n", (const char*)Retrieve(e));
}
else
{
printf("Not found [key:%s]\n", cur);
}
system("pause");
}