HashTableBucket.h
#pragma once
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
//typedef char* HTBKeyType;
//typedef char* HTBValueType;
//typedef char* HTBKeyType;
//typedef int HTBValueType;
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);
void TestHashTableBucket();
HashTableBucket.c
#include "HashTableBucket.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];
}
//初始化
void HTBInit(HTB* htb, size_t len)
{
assert(htb);
根据素数表获取哈希表的长度
htb->_len = GetNextPrime(len);
htb->_size = 0;
//为哈希表开辟空间
htb->_tables = (HashNode**)malloc(sizeof(HashNode*)*htb->_len);
//将哈希表中的所有指针初始化为空
memset(htb->_tables, 0, sizeof(HashNode*)*htb->_len);
}
//销毁
void HTBDestory(HTB* htb)
{
assert(htb);
//释放哈希表上每一条链上的节点
for (size_t i = 0; 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;
}
int HTBHashFunc(HTBKeyType key, int len)
{
//return StrHash(key) % len;
return key % len;
}
//检查负载因子是否达到1,如果达到1,则需要扩容
void HTBCheckCapacity(HTB* htb)
{
assert(htb);
if (htb->_size == htb->_len)
{
HTB newhtb;
newhtb._len = GetNextPrime(htb->_len);
HTBInit(&newhtb, newhtb._len);
for (size_t 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;
}
}
//创建节点
HashNode* BuyHashNode(HTBKeyType key, HTBValueType value)
{
HashNode* node = malloc(sizeof(HashNode));
node->_key = key;
node->_value = value;
node->_next = NULL;
return node;
}
//插入一个元素
int HTBInsert(HTB* htb, HTBKeyType key, HTBValueType value)
{
assert(htb);
HashNode* cur, *newNode;
HTBCheckCapacity(htb);
int 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)
{
assert(htb);
HashNode* cur = NULL, *prev = NULL;
int 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)
{
assert(htb);
HashNode* cur;
int 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)
{
assert(htb);
for (size_t i = 0; i < htb->_len; ++i)
{
int count = 0;
HashNode* cur = htb->_tables[i];
printf("桶[%d]->", i);
while (cur)
{
printf("[%s:%s]->", cur->_key, cur->_value);
++count;
cur = cur->_next;
}
printf("%d\n", count);
}
printf("\n");
}
void TestHashTableBucket()
{
HTB htb;
HTBInit(&htb, 10);
HTBInsert(&htb, "insert", "插入");
HTBInsert(&htb, "delete", "删除");
HTBInsert(&htb, "hash", "哈希");
HTBInsert(&htb, "test", "测试");
HTBPrint(&htb);
HTBRemove(&htb, "test");
HTBPrint(&htb);
}
int main()
{
TestHashTableBucket();
return 0;
}