1.使用哈希桶处理整型数据
1)HashTableBucket.h
#ifndef _HASHTABLEBUCKET_H__
#define _HASHTABLEBUCKET_H__
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include <string.h>
static size_t GetNextPrime(size_t value)
{
int i = 0;
//const int _PrimeSize = 28;
static const unsigned long _PrimeList[28] =
{
53ul, 97ul, 193ul, 389ul, 769ul,
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
1610612741ul, 3221225473ul, 4294967291ul
};
for (; i < 28; ++i)
{
if (_PrimeList[i] > value)
{
return _PrimeList[i];
}
}
return _PrimeList[27];
}
static size_t StrHash(const char* str)
{
size_t hash = 0;
size_t seed = 131;
while (*str)
{
/*hash += *str;*/
hash = hash*seed + *str;
++str;
}
/*printf("%u\n", hash);*/
return hash;
}
typedef int HTBKeyType;
typedef int HTBValueType;
typedef struct HashNode
{
struct HashNode* _next;
HTBKeyType _key;
HTBValueType _value;
}HashNode;
typedef struct HashTableBucket
{
HashNode** _tables;
size_t _size;
size_t _len;
}HTB;
void HTBInit(HTB* htb, size_t len);
void HTBDestory(HTB* htb);
int HTBInsert(HTB* htb, HTBKeyType key, HTBValueType value);
int HTBRemove(HTB* htb, HTBKeyType key);
HashNode* HTBFind(HTB* htb, HTBKeyType key);
int HTBSize(HTB* htb);
int HTBEmpty(HTB* htb);
#endif
2)HashTableBucket.c
#include "HashTableBucket.h"
void HTBInit(HTB* htb, size_t len)
{
assert(htb);
//根据素数表获取哈希表的长度
int HTB_len = GetNextPrime(len);
//为哈希桶开辟空间(
HashNode** table = (HashNode**)malloc(sizeof(HashNode*)*(HTB_len));
if (table == NULL)
{
perror("use malloc of create");
exit(EXIT_FAILURE);
}
htb->_tables = table;
htb->_size = 0;
htb->_len = HTB_len;
//将哈希表中的所有指针初始化为空,否则会对野指针操作
memset(htb->_tables,0, sizeof(HashNode*)*(htb->_len));
}
void HTBDestory(HTB* htb)
{
unsigned int i = 0;
assert(htb);
for (; i < htb->_len; ++i)
{
HashNode* cur = htb->_tables[i];
while (cur)
{
HashNode* next = cur->_next;
free(cur);
cur = next;
}
htb->_tables[i] = NULL;
}
free(htb->_tables);
htb->_tables = NULL;
htb->_size = 0;
htb->_len = 0;
}
//哈希函数,计算哈希地址(整数)
static int HTBHashFunc(HTBKeyType key, int len)
{
return key%len;
}
HashNode* BuyHashNode(HTBKeyType key, HTBValueType value)
{
HashNode* node = malloc(sizeof(HashNode));
if (node != NULL)
{
node->_key = key;
node->_value = value;
node->_next = NULL;
}
return node;
}
void HTBCheckCapacity(HTB* htb)
{
assert(htb);
if (htb->_size == htb->_len)
{
unsigned int i;
HTB newhtb;
newhtb._len = GetNextPrime(htb->_len);
HTBInit(&newhtb, newhtb._len);
if (htb->_size == htb->_len)
{
for (i = 0; i < htb->_len; ++i)
{
HashNode* cur = htb->_tables[i];
while (cur)
{
//记录下一个结点的位置
HashNode* next = cur->_next;
size_t index = HTBHashFunc(cur->_key, newhtb._len);
//头插到新的哈希表中
cur->_next = newhtb._tables[index];
newhtb._tables[index] = cur;
cur = next;
}
htb->_tables[i] = NULL;
}
}
HTBDestory(htb);
htb->_tables = newhtb._tables;
htb->_size = newhtb._size;
htb->_len = newhtb._len;
}
}
int HTBInsert(HTB* htb, HTBKeyType key, HTBValueType value)
{
size_t index;
HashNode* cur, *newNode;
HTBCheckCapacity(htb);
assert(htb);
index = HTBHashFunc(key, htb->_len);
cur = htb->_tables[index];
while (cur)
{
if (cur->_key == key)
return -1;
cur = cur->_next;
}
newNode = BuyHashNode(key, value);
newNode->_next = htb->_tables[index];
htb->_tables[index] = newNode;
htb->_size++;
return 0;
}
int HTBRemove(HTB* htb, HTBKeyType key)
{
size_t index;
HashNode* cur = NULL, *prev = NULL;
assert(htb);
index = HTBHashFunc(key, htb->_len);
cur = htb->_tables[index];
while (cur)
{
if (cur->_key == key)
{
if (prev == NULL)
htb->_tables[index] = cur->_next;
else
prev->_next = cur->_next;
free(cur);
--htb->_size;
return 0;
}
prev = cur;
cur = cur->_next;
}
return -1;
}
HashNode* HTBFind(HTB* htb, HTBKeyType key)
{
size_t index;
HashNode* cur;
assert(htb);
index = HTBHashFunc(key, htb->_len);
cur = htb->_tables[index];
while (cur)
{
if (cur->_key == key)
{
return cur;
}
cur = cur->_next;
}
return NULL;
}
int HTBSize(HTB* htb)
{
assert(htb);
return htb->_size == 0 ? 0 : 1;
}
int HTBEmpty(HTB* htb)
{
assert(htb);
return htb->_size == htb->_len ? 0 : 1;
}
void HTBPrint(HTB* htb)
{
unsigned int i = 0;
assert(htb);
for (i=0; i < htb->_len; ++i)
{
int count = 0;
printf("table[%d]->", i);
HashNode* cur = htb->_tables[i];
while (cur)
{
printf("([key:%d}:{value:%d])->", cur->_key, cur->_value);
count++;
cur = cur->_next;
}
printf("(count=%d)->over\n", count);
}
}
3)Test.c
#include "HashTableBucket.h"
void HTBtest1()
{
HTB htb;
HTBInit(&htb, 10);
HTBInsert(&htb, 6, 0);
HTBInsert(&htb, 11, 0);
HTBPrint(&htb);
}
int main()
{
HTBtest1();
system("pause");
return 0;
}
2.使用哈希桶处理字符数据
1)HashTableBucket.h
#ifndef _HASHTABLEBUCKET_H__
#define _HASHTABLEBUCKET_H__
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include <string.h>
static size_t GetNextPrime(size_t value)
{
int i = 0;
//const int _PrimeSize = 28;
static const unsigned long _PrimeList[28] =
{
53ul, 97ul, 193ul, 389ul, 769ul,
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
1610612741ul, 3221225473ul, 4294967291ul
};
for (; i < 28; ++i)
{
if (_PrimeList[i] > value)
{
return _PrimeList[i];
}
}
return _PrimeList[27];
}
static size_t StrHash(const char* str)
{
size_t hash = 0;
size_t seed = 131;
while (*str)
{
/*hash += *str;*/
hash = hash*seed + *str;
++str;
}
/*printf("%u\n", hash);*/
return hash;
}
//
typedef char* HTBKeyType;
typedef char* HTBValueType;
typedef struct HashNode
{
struct HashNode* _next;
HTBKeyType _key;
HTBValueType _value;
}HashNode;
typedef struct HashTableBucket
{
HashNode** _tables;
size_t _size;
size_t _len;
}HTB;
void HTBInit(HTB* htb, size_t len);
void HTBDestory(HTB* htb);
int HTBInsert(HTB* htb, HTBKeyType key, HTBValueType value);
int HTBRemove(HTB* htb, HTBKeyType key);
HashNode* HTBFind(HTB* htb, HTBKeyType key);
int HTBSize(HTB* htb);
int HTBEmpty(HTB* htb);
#endif
2)HashTableBucket.c
#include "HashTableBucket.h"
void HTBInit(HTB* htb, size_t len)
{
assert(htb);
//根据素数表获取哈希表的长度
int HTB_len = GetNextPrime(len);
//为哈希桶开辟空间(
HashNode** table = (HashNode**)malloc(sizeof(HashNode*)*(HTB_len));
if (table == NULL)
{
perror("use malloc of create");
exit(EXIT_FAILURE);
}
htb->_tables = table;
htb->_size = 0;
htb->_len = HTB_len;
//将哈希表中的所有指针初始化为空,否则会对野指针操作
memset(htb->_tables,0, sizeof(HashNode*)*(htb->_len));
}
void HTBDestory(HTB* htb)
{
unsigned int i = 0;
assert(htb);
for (; i < htb->_len; ++i)
{
HashNode* cur = htb->_tables[i];
while (cur)
{
HashNode* next = cur->_next;
free(cur);
cur = next;
}
htb->_tables[i] = NULL;
}
free(htb->_tables);
htb->_tables = NULL;
htb->_size = 0;
htb->_len = 0;
}
size_t HTBHashFunc(HTBKeyType key, size_t len)
{
int count = 0;
int i = 0;
while (*(key + i) != '\0')
{
count += *(key + i);
++i;
}
return count%len;
}
HashNode* BuyHashNode(HTBKeyType key, HTBValueType value)
{
HashNode* node = malloc(sizeof(HashNode));
if (node != NULL)
{
node->_key = key;
node->_value = value;
node->_next = NULL;
}
return node;
}
void HTBCheckCapacity(HTB* htb)
{
assert(htb);
if (htb->_size == htb->_len)
{
unsigned int i;
HTB newhtb;
newhtb._len = GetNextPrime(htb->_len);
HTBInit(&newhtb, newhtb._len);
if (htb->_size == htb->_len)
{
for (i = 0; i < htb->_len; ++i)
{
HashNode* cur = htb->_tables[i];
while (cur)
{
//记录下一个结点的位置
HashNode* next = cur->_next;
size_t index = HTBHashFunc(cur->_key, newhtb._len);
//头插到新的哈希表中
cur->_next = newhtb._tables[index];
newhtb._tables[index] = cur;
cur = next;
}
htb->_tables[i] = NULL;
}
}
HTBDestory(htb);
htb->_tables = newhtb._tables;
htb->_size = newhtb._size;
htb->_len = newhtb._len;
}
}
int HTBInsert(HTB* htb, HTBKeyType key, HTBValueType value)
{
size_t index;
HashNode* cur, *newNode;
HTBCheckCapacity(htb);
assert(htb);
index = HTBHashFunc(key, htb->_len);
cur = htb->_tables[index];
while (cur)
{
if (cur->_key == key)
return -1;
cur = cur->_next;
}
newNode = BuyHashNode(key, value);
newNode->_next = htb->_tables[index];
htb->_tables[index] = newNode;
htb->_size++;
return 0;
}
int HTBRemove(HTB* htb, HTBKeyType key)
{
size_t index;
HashNode* cur = NULL, *prev = NULL;
assert(htb);
index = HTBHashFunc(key, htb->_len);
cur = htb->_tables[index];
while (cur)
{
if (cur->_key == key)
{
if (prev == NULL)
htb->_tables[index] = cur->_next;
else
prev->_next = cur->_next;
free(cur);
--htb->_size;
return 0;
}
prev = cur;
cur = cur->_next;
}
return -1;
}
HashNode* HTBFind(HTB* htb, HTBKeyType key)
{
size_t index;
HashNode* cur;
assert(htb);
index = HTBHashFunc(key, htb->_len);
cur = htb->_tables[index];
while (cur)
{
if (cur->_key == key)
{
return cur;
}
cur = cur->_next;
}
return NULL;
}
int HTBSize(HTB* htb)
{
assert(htb);
return htb->_size == 0 ? 0 : 1;
}
int HTBEmpty(HTB* htb)
{
assert(htb);
return htb->_size == htb->_len ? 0 : 1;
}
void HTBPrint(HTB* htb)
{
unsigned int i = 0;
assert(htb);
for (i=0; i < htb->_len; ++i)
{
int count = 0;
printf("table[%d]->", i);
HashNode* cur = htb->_tables[i];
while (cur)
{
printf("([key:%s}:{value:%s])->", cur->_key, cur->_value);
count++;
cur = cur->_next;
}
printf("(count=%d)->over\n", count);
}
}
3)Test.c
#include "HashTableBucket.h"
void HTBtest2()
{
HTB htb;
HTBInit(&htb, 10);
HTBInsert(&htb, "insert", "插入");
HTBInsert(&htb, "delete", "删除");
HTBInsert(&htb, "hash", "哈希");
HTBInsert(&htb, "test", "测试");
HTBPrint(&htb);
}
int main()
{
HTBtest2();
system("pause");
return 0;
}