了解哈希的基本概念可以看这里:搜索结构之哈希
闭散列代码:闭散列
#pragma once
#include<stdio.h>
#include<assert.h>
#include<malloc.h>
#include"Comm.h"
typedef int DataType;
typedef enum State
{
EMPTY, //当前位置为空
EXIST, //当前位置有元素
DELETE //当前位置被删除
}State;
//元素
typedef struct Elem
{
DataType _data;
State _state;
}Elem;
typedef enum
{
_IsLine, //线性探测
_IsNotLine //二次探测
}IsLine;
typedef size_t(*PDT)(DataType str);
typedef struct HashTable
{
Elem* _table;
int _capacity; //容量
int _size; //存在位元素个数
int _total; //存在位和删除位总共的个数
IsLine _Dete; //探测方法
PDT _setData; //将数据转换为类型
}HashTable;
void HashTableInit(HashTable* ht,int capacity, IsLine _Dete, PDT setData);
void HashTableInsert(HashTable* ht,DataType data);
void HashTableDelete(HashTable* ht, DataType data);
int HashTableSize(HashTable* ht);
int HashTableEmpty(HashTable* ht);
void HashTableDestroy(HashTable* ht);
int HashFind(HashTable* ht, DataType data);
#include"Hash.h"
//哈希函数
DataType HashFunc(HashTable* ht, DataType data)
{
assert(ht);
return data % ht->_capacity;
}
//检测容量
int CheckCapacity(HashTable* ht)
{
assert(ht);
if ((ht->_total * 10) / (ht->_capacity) > 7)
return 1;
return 0;
}
//线性探测
int IsLineDete(HashTable* ht, DataType HashAddr)
{
HashAddr = HashAddr + 1;
if (HashAddr == ht->_capacity)
HashAddr = 0;
return HashAddr;
}
//二次探测
int DeteTwo(HashTable* ht, int HashAddr, int i)
{
HashAddr = HashAddr + 2 * i + 1;
//越界
if (HashAddr >= ht->_capacity)
HashAddr = HashAddr%ht->_capacity;
return HashAddr;
}
void _Swap(int* newht, int* ht)
{
int temp = *newht;
*newht = *ht;
*ht = temp;
}
//交换哈希表
void Swap(HashTable* newht, HashTable* ht)
{
assert(newht);
assert(ht);
Elem* pTemp = newht->_table;
newht->_table = ht->_table;
ht->_table = pTemp;
_Swap(&newht->_capacity, &ht->_capacity);
_Swap(&newht->_size, &ht->_size);
_Swap(&newht->_total, &ht->_total);
}
void BuyCapacity(HashTable* ht)
{
assert(ht);
HashTable newht;
int i = 0;
int NewCapacity = GetCapacity(ht->_capacity);
//初始化新的哈希表
HashTableInit(&newht, NewCapacity, ht->_Dete, ht->_setData);
//拷贝元素
for (; i < ht->_capacity; ++i)
{
if (ht->_table[i]._state = EXIST)
HashTableInsert(&newht, ht->_table[i]._data);
}
//交换
Swap(&newht, ht);
HashTableDestroy(&newht);
}
//初始化
void HashTableInit(HashTable* ht,int capacity, IsLine _Dete, PDT setData)
{
int i = 0;
assert(ht);
capacity = GetCapacity(capacity);
ht->_table = (Elem*)malloc(sizeof(Elem)* capacity);
if (NULL == ht->_table)
return;
for (; i < capacity; ++i)
{
ht->_table[i]._state = EMPTY;
}
ht->_capacity = capacity;
ht->_size = 0;
ht->_total = 0;
ht->_setData = setData;
ht->_Dete = _Dete;
}
//插入
void HashTableInsert(HashTable* ht, DataType data)
{
assert(ht);
DataType HashAddr = 0;
int i = 0;
int NewData = 0;
//判断负载因子
if (CheckCapacity(ht))
{
BuyCapacity(ht);
}
NewData = ht->_setData(data);
HashAddr = HashFunc(ht, NewData);
while (EMPTY != ht->_table[i]._state)
{
if (ht->_table[HashAddr]._state == EMPTY)
{
if (ht->_table[i]._data = data)
return;
}
//线性探测
if (ht->_Dete == _IsLine)
HashAddr = IsLineDete(ht, HashAddr);
else
HashAddr = DeteTwo(ht, HashAddr, ++i);
}
//状态为空,直接插入
ht->_table[HashAddr]._data = data;
ht->_table[HashAddr]._state = EXIST;
++ht->_size;
++ht->_total;
}
void HashTableDelete(HashTable* ht, DataType data)
{
assert(ht);
int ret = HashFind(ht, data);
if (ret != -1)
{
ht->_table[ret]._state = DELETE;
--ht->_size;
}
}
int HashTableSize(HashTable* ht)
{
assert(ht);
return ht->_size;
}
int HashTableEmpty(HashTable* ht)
{
assert(ht);
return 0 == ht->_size;
}
int HashFind(HashTable* ht, DataType data)
{
assert(ht);
int starAddr = 0;
DataType HashAddr = 0;
int i = 0;
int NewData = ht->_setData(data);
HashAddr = HashFunc(ht, NewData);
starAddr = HashAddr;
while (EMPTY != ht->_table[HashAddr]._state)
{
if (EXIST == ht->_table[HashAddr]._state)
{
if (data == ht->_table[HashAddr]._data)
return HashAddr;
}
//线性探测
if (ht->_Dete == _IsLine)
{
HashAddr = IsLineDete(ht, HashAddr);
//未找到
if (HashAddr == starAddr)
return -1;
}
else
HashAddr = DeteTwo(ht, HashAddr, ++i);
}
return -1;
}
void HashTableDestroy(HashTable* ht)
{
assert(ht);
free(ht->_table);
ht->_capacity = 0;
ht->_size = 0;
ht->_total = 0;
ht->_table = NULL;
}