完整代码块
/***************************************/
//Hash_OP.h
#define MAX_SIZE 10
//typedef int DataType;
typedef char *DataType;
typedef int(*PDTInt)(DataType data);//转int类型
typedef enum{ EXIST, EMPTY, DELETE }State;
typedef struct HTElem
{
DataType _data;
State _state;
}HTElem;
typedef struct HashTable
{
HTElem *_pHt;
int _capacity;
int _size;//计算哈希表中有效元素的个数
int _total; //EXIST和DELETEl两个元素之和
PDTInt _PDTInt;//转int类型
}HashTable, HT;
//哈希表的初始化
void InitHashTable(HT *ht, int capacity, PDTInt pDTInt);
//哈希表的插入
void InsertHashTable(HT *ht, DataType data);
//哈希表的删除
void DeleteHashTable(HT *ht, DataType data);
//哈希表的查找
int FindHashTable(HT *ht, DataType data);
//计算哈希表长度
int SizeHashTable(HT *ht);
//哈希表的判空
int EmptyHashTable(HT *ht);
//计算哈希地址
int FuncHash(HT *ht, DataType data);
//增容
void _CheckCapacity(HT *ht);
//销毁
void DestroyHashTable(HT *ht);
/***************************************/
//Hash_OP.c
#include <assert.h>
#include <malloc.h>
#include <stdlib.h>
#include "Common.h"
//哈希表的初始化
void InitHashTable(HT *ht, int capacity, PDTInt pDTInt)
{
assert(ht);
int i = 0;
capacity = GetNextPrime(capacity);
ht->_pHt = (HTElem*)malloc(capacity * sizeof(HTElem));
if (NULL == ht->_pHt)
{
assert(0);
return;
}
ht->_capacity = capacity;
for (; i < capacity; ++i)
ht->_pHt[i]._state = EMPTY;
ht->_size = 0;
ht->_total = 0;
ht->_PDTInt = pDTInt;
}
//增容
void _CheckCapacity(HT *ht)
{
assert(ht);
int hashAddr = 0;
//哈希负载因子
if (ht->_total * 10 / ht->_capacity >= 7)
{
//1.开辟新空间
int oldCapacity = ht->_capacity;
int newCapacity = GetNextPrime(ht->_capacity);
HTElem *pNew = (HTElem *)malloc(newCapacity * sizeof(HTElem));
int i = 0;
if (NULL == pNew)
{
assert(0);
return;
}
//2.拷贝元素
for (i = 0; i < newCapacity; ++i)
pNew[i]._state = EMPTY;
//只拷贝状态为存在的元素
ht->_capacity = newCapacity;
for (i = 0; i < oldCapacity; ++i)
{
if (EXIST != ht->_pHt[i]._state)
continue;
hashAddr = FuncHash(ht, ht->_pHt[i]._data);
//找存储位置
while (EMPTY != ht->_pHt[hashAddr]._state)
{
#if 0
//线性探测
hashAddr++;
if (hashAddr == ht->_capacity)//越界了,从头开始访问
hashAddr = 0;
#else
//二次探测
i++;
hashAddr = hashAddr + 2 * i + 1;
if (hashAddr >= ht->_capacity)
hashAddr %= ht->_capacity;
#endif
}
//插入元素
ht->_pHt[hashAddr]._data = ht->_pHt[i]._data;
ht->_pHt[hashAddr]._state = EXIST;
}
//3.释放旧空间
free(ht->_pHt);
ht->_pHt = pNew;
ht->_total = ht->_size;
}
}
//哈希表的插入
void InsertHashTable(HT *ht, DataType data)
{
int hashAddr;
int i = 0;
assert(ht);
//检测容量
_CheckCapacity(ht);
//计算哈希地址
hashAddr = FuncHash(ht, data);
//找存储位置
while (EMPTY != ht->_pHt[hashAddr]._state)
{
if (EXIST == ht->_pHt[hashAddr]._state)
{
if (data == ht->_pHt[hashAddr]._data)
return;
}
#if 0
//线性探测
hashAddr++;
if (hashAddr == ht->_capacity)//越界了,从头开始访问
hashAddr = 0;
#else
//二次探测
i++;
hashAddr = hashAddr + 2 * i + 1;
if (hashAddr >= ht->_capacity)
hashAddr %= ht->_capacity;
#endif
}
//插入元素
ht->_pHt[hashAddr]._data = data;
ht->_pHt[hashAddr]._state = EXIST;
ht->_size++;
ht->_total++;
}
//哈希表的删除
void DeleteHashTable(HT *ht, DataType data)
{
assert(ht);
if (-1 != FindHashTable(ht, data))
{
ht->_pHt[FindHashTable(ht, data)]._state = DELETE;
ht->_size--;
}
}
//哈希表的查找
int FindHashTable(HT *ht, DataType data)
{
int hashAddr;
int i = 0;
assert(ht);
hashAddr = FuncHash(ht, data);
while (EMPTY != ht->_pHt[hashAddr]._state)
{
if (EXIST == ht->_pHt[hashAddr]._state)
{
if (data == ht->_pHt[hashAddr]._data)
return hashAddr;
}
#if 0
hashAddr++;
if (hashAddr == ht->_capacity)//越界了,从头开始访问
hashAddr = 0;
#else
//二次探测
i++;
hashAddr = hashAddr + 2 * i + 1;
if (hashAddr >= ht->_capacity)
hashAddr %= ht->_capacity;
#endif
}
return -1;
}
//计算哈希表长度
int SizeHashTable(HT *ht)
{
assert(ht);
return ht->_size;
}
//哈希表的判空
int EmptyHashTable(HT *ht)
{
assert(ht);
return 0 == ht->_size;
}
//计算哈希地址
int FuncHash(HT *ht, DataType data)
{
assert(ht);
return ht->_PDTInt(data) % ht->_capacity;
}
//销毁
void DestroyHashTable(HT *ht)
{
assert(ht);
free(ht->_pHt);
ht->_pHt = NULL;
ht->_capacity = 0;
ht->_size = 0;
ht->_total;
}
/***************************************/
//Common.h
#pragma once
//素数表
unsigned long GetNextPrime(unsigned long prime);
//字符串类型
unsigned long StrToINT(const char * str);
//默认转化方法
unsigned long DefToINT(long data);
/
//Common.c
#define PRIME_SIZE 28
//素数表
unsigned long GetNextPrime(unsigned long prime)
{
// 使用素数表对齐做哈希表的容量,降低哈希冲突
static const unsigned long _PrimeList [PRIME_SIZE] =
{
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
};
int i = 0;
for (i = 0; i < PRIME_SIZE; ++i)
{
if (_PrimeList[i] > prime)
return _PrimeList[i];
}
return _PrimeList[PRIME_SIZE - 1];
}
//字符串类型
unsigned long StrToINT(const char * str)
{
unsigned int seed = 131; // 31 131 1313 13131 131313
unsigned int hash = 0;
while (*str)
{
hash = hash * seed + (*str++);
}
return (hash & 0x7FFFFFFF);
}
//默认转化方法
unsigned long DefToINT(long data)
{
return data;
}
/***************************************/
//test.c
#include "Hash_OP.h"
#include <stdio.h>
void TestHash_OP()
{
HashTable ht;
InitHashTable(&ht, 10, DefToINT);
InsertHashTable(&ht, 23);
InsertHashTable(&ht, 14);
InsertHashTable(&ht, 35);
InsertHashTable(&ht, 22);
InsertHashTable(&ht, 27);
InsertHashTable(&ht, 17);
printf("size = %d\n", SizeHashTable(&ht));
if (-1 == FindHashTable(&ht, 17))
printf("17 这个元素不存在\n");
else
printf("17 这个元素存在\n");
if (-1 == FindHashTable(&ht, 37))
printf("37 这个元素不存在\n");
else
printf("37 这个元素存在\n");
InitHashTable(&ht, 10, StrToINT);
InsertHashTable(&ht, "23");
InsertHashTable(&ht, "14");
InsertHashTable(&ht, "35");
InsertHashTable(&ht, "22");
InsertHashTable(&ht, "27");
InsertHashTable(&ht, "17");
printf("size = %d\n", SizeHashTable(&ht));
if (-1 == FindHashTable(&ht, "17"))
printf("字符17 这个元素不存在\n");
else
printf("字符17 这个元素存在\n");
if (-1 == FindHashTable(&ht, "37"))
printf("字符37 这个元素不存在\n");
else
printf("字符37 这个元素存在\n");
DestroyHashTable(&ht);
}
int main()
{
TestHash_OP();
system("pause");
return 0;
}
结果输出: