HashTable.h:
#include<stddef.h>
#define HashMaxSize 1000
typedef int KeyType;
typedef int ValueType;
typedef size_t(*HashFunc)(KeyType key);
typedef struct HashElem{
KeyType key;
ValueType value;
struct HashElem* next;
}HashElem;
typedef struct HashTable{
HashElem* data[HashMaxSize];
size_t size;
HashFunc hash_func;
}HashTable;
void HashInit(HashTable* ht, HashFunc hash_func);
// 约定哈希表中不能包含 key 相同的值.
void HashInsert(HashTable* ht, KeyType key, ValueType value);
int HashFind(HashTable* ht, KeyType key, ValueType* value);
void HashRemove(HashTable* ht, KeyType key);
size_t HashSize(HashTable* ht);
int HashEmpty(HashTable* ht);
void HashDestroy(HashTable* ht);
HashTable.c
#include"HashTable.h"
#include<stdlib.h>
size_t HashFuncDefault(KeyType key){
return key%HashMaxSize;
}
void HashInit(HashTable* ht, HashFunc hash_func){
if (ht == NULL){
return;
}
ht->size = 0;
ht->hash_func = hash_func;
size_t i = 0;
for (; i < HashMaxSize; i++){
ht->data[i] = NULL;
}
}
//法1.
HashElem* HashBucketFind(HashTable* head, KeyType key){
HashElem* cur = head;
for (; cur != NULL; cur = cur->next){
if (cur->key == key){
return cur;
}
}
return NULL;
}
//法2.
int HashBucketFindCur_Prev(HashTable* head, KeyType key, HashElem**cur_out, HashElem** pre_out){
HashElem* prev = NULL;
HashElem* cur = head;
for (; cur != NULL; prev = cur, cur = cur->next){
if (cur->key == key){
*cur_out = cur;
*pre_out = prev;
return 1;
}
}
return 0;
}
HashElem* HashCreate(KeyType key, ValueType value){
HashElem* new_node = (HashElem*)malloc(sizeof(HashElem));
new_node->key = key;
new_node->next = NULL;
new_node->value = value;
return new_node;
}
void HashInsert(HashTable* ht, KeyType key, ValueType value){
if (ht == NULL){
return;
}
size_t offset =ht->hash_func(key);
HashElem* res = HashBucketFind(ht->data[offset], key);
if (res != NULL){
return;
}
else{
HashElem* new_node = HashCreate(key, value);//采用头插
new_node->next = ht->data[offset];
ht->data[offset] = new_node;
++(ht->size);
}
}
int HashFind(HashTable* ht, KeyType key, ValueType* value){
if (ht == NULL){
return 0;
}
size_t offset = ht->hash_func(key);
HashElem* cur = ht->data[offset];
while (cur != NULL){
if (cur->key == key){
*value = cur->value;
return 1;
}
cur = cur->next;
}
return 0;
}
void HashDestroy(HashTable* ht){
if (ht == NULL){
return;
}
size_t i = 0;
for (; i < HashMaxSize; i++){
if (ht->data[i] != NULL){
ht->data[i] = NULL;
}
}
ht->size = 0;
ht->hash_func = NULL;
}
void Destroy(HashElem* head){
if (head == NULL){
return;
}
free(head);
}
void HashRemove(HashTable* ht, KeyType key){
//法1.
//if (ht == NULL){
// return;
//}
//size_t offset = ht->hash_func(key);
//HashElem* cur = ht->data[offset];
//HashElem* prev = cur;
//if (cur != NULL&&cur->key == key){
// ht->data[offset] = cur->next;//恰好要删除的是第一个元素
// free(cur);
// --ht->size;
//}
//else{
// while (cur != NULL){
// if (cur->key == key){
// prev->next = cur->next;
// free(cur);
// --ht->size;
// return;;
// }
// prev = cur;
// cur = cur->next;
// }
//}
//法2.
if (ht == NULL){
return;
}
size_t offset = ht->hash_func(key);
HashElem* prev = NULL;
HashElem* cur = NULL;
int ret = HashBucketFindCur_Prev(ht->data[offset], key,&cur,&prev);
if (ret == 0){
return;
}
if (cur == ht->data[offset]){
ht->data[offset] = cur->next;
}
else{
prev->next = cur->next;
}
Destroy(cur);
ht->size--;
}
int HashEmpty(HashTable* ht){
if (ht == NULL){
return;
}
return ht->size == 0;
}
size_t HashSize(HashTable* ht){
if (ht == NULL||ht->data==NULL){
return 0;
}
return ht->size;
}
////////////////////////////////////////////////////
//测试代码
////////////////////////////////////////////////////
#if 1
#include<stdio.h>
#define TEST_HEADER printf("\n=========================%s=======================\n",__FUNCTION__);
void Display(HashTable* ht){
size_t i = 0;
for (; i < HashMaxSize; i++){
if (ht->data[i] == NULL){
continue;
}
HashElem* cur = ht->data[i];
for (; cur != NULL; cur = cur->next){
printf("%lu-> %d %d\n", i,cur->key, cur->value);
}
}
}
void testHashInit(){
TEST_HEADER;
HashTable ht;
HashInit(&ht, HashFuncDefault);
printf("ht.size expect 0,actual %lu\n", ht.size);
printf("ht->hashfunc expect %p,actual %p\n", HashFuncDefault, ht.hash_func);
int i = 0;
for (; i < HashMaxSize; i++){
if (ht.data[i] != NULL){
printf("初始化不成功");
}
}
}
void testHashInsert(){
TEST_HEADER;
HashTable ht;
HashInit(&ht, HashFuncDefault);
HashInsert(&ht, 1, 100);
HashInsert(&ht, 2, 200);
HashInsert(&ht, 1001, 300);
HashInsert(&ht, 1002, 400);
printf("插入四个元素:\n");
Display(&ht);
}
void testHashFind(){
TEST_HEADER;
HashTable ht;
HashInit(&ht, HashFuncDefault);
HashInsert(&ht, 1, 100);
HashInsert(&ht, 2, 200);
HashInsert(&ht, 1001, 300);
HashInsert(&ht, 1002, 400);
int value=0;
int ret=HashFind(&ht, 1001, &value);
printf("ret expect 1,actual %d\n", ret);
printf("value expect 300,actual %d\n", value);
ret = HashFind(&ht, 1003, &value);
printf("ret expect 0,actual %d\n", ret);
}
void testHashRemove(){
TEST_HEADER;
HashTable ht;
HashInit(&ht, HashFuncDefault);
HashInsert(&ht, 1, 100);
HashInsert(&ht, 2, 200);
HashInsert(&ht, 1001, 300);
HashInsert(&ht, 1002, 400);
Display(&ht);
printf("ht->size=%d\n", ht.size);
HashRemove(&ht, 1);
printf("ht->size=%d\n", ht.size);
Display(&ht);
printf("删除第一个元素:\n");
HashRemove(&ht, 1001);
printf("ht->size=%d\n", ht.size);
}
void testHashDestroy(){
TEST_HEADER;
HashTable ht;
HashInit(&ht, HashFuncDefault);
HashInsert(&ht, 1, 100);
HashInsert(&ht, 2, 200);
HashInsert(&ht, 1001, 300);
HashInsert(&ht, 1002, 400);
Display(&ht);
printf("销毁哈希表\n");
HashDestroy(&ht);
Display(&ht);
}
void testHashEmpty(){
TEST_HEADER;
HashTable ht;
HashInit(&ht, HashFuncDefault);
printf("expect 1 actual %d\n",HashEmpty(&ht));
}
void testHashSize(){
TEST_HEADER;
HashTable ht;
HashInit(&ht, HashFuncDefault);
/*HashInsert(&ht, 1, 100);
HashInsert(&ht, 2, 200);
HashInsert(&ht, 1001, 300);
HashInsert(&ht, 1002, 400);
printf("expect 4 actual %d\n", HashSize(&ht));*/
printf("expect 0 actual %d\n", HashSize(&ht));
}
int main(){
//testHashInit();
//testHashInsert();
//testHashFind();
//testHashRemove();
//testHashDestroy();
//testHashEmpty();
testHashSize();
system("pause");
return 0;
}
#endif