本文哈希函数为:除留余数法。
本文哈希冲突的处理方法:
闭散列:也叫开放地址法,当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有空位置,那么可以把key存放到表中 “下一个” 空位中去 。
二次探测:二次探查法在表中寻找“下一个”空位置的公式为:Hi+1 = Hi + (i + 1)^2,Hi =H0 + i^2 。化简后为Hi+1 = i * 2 + 1。
HashTable.h
#pragma once
#include<Windows.h>
#include<assert.h>
#include<stdio.h>
#define N 10
typedef enum{EMPTY,DELET, EXIST}State; //三种状态,空,删除,存在
typedef int DataType;
typedef struct HTEmle
{
DataType _data;
int State;
}HTEmle;
typedef struct HashTable
{
HTEmle _arr[N];
int _size; //有效数据
int _totle; //总数据个数,包括无效的
int _IsLineDetect; //是否为线性探测, 1为线性探测,2为二次探测
}HashTable, HT;
//线性探测
int IsLineDetect(HT *ht,int addr);
//二次探测
int IsLineDetect2(HT *ht, int addr);
//计算地址
int HashTableAddr(DataType data);
//哈希表的初始化
void HashTableInit(HT *ht, int IsLine);
//哈希表的插入
void HashTableInsert(HT *ht, DataType data);
//哈希表的删除
void HashTableDelete(HT *ht, DataType data);
//查找哈希表中某个元素
int HashTableFind(HT *ht, DataType data);
//计算哈希表中元素的个数
int HashTableSize(HT *ht);
//判断哈希表是否为空
int HashTableEmpty(HT *ht);
HashTable.c
#include"HashTable.h"
//线性探测
int IsLineDetect(HT *ht, int addr)
{
//判断地址是否合法
while (EMPTY != ht->_arr[addr].State)
{
//不合法,则找合法地址
++addr;
if (addr >= N)
addr = 0;
}
return addr;
}
//二次探测
int IsLineDetect2(HT *ht, int addr)
{
int times = 0;
while (EMPTY != ht->_arr[addr].State)
{
addr += times * 2 + 1;
if (addr >= N)
addr = addr % N;
times++;
}
return addr;
}
//计算地址
int HashTableAddr(DataType data)
{
return data % N;
}
//哈希表的初始化
void HashTableInit(HT *ht, int IsLine)
{
int i = 0;
assert(ht);
for (; i < N; ++i)
ht->_arr[i].State = EMPTY;
ht->_size = 0;
ht->_totle = 0;
if (1 == IsLine)
ht->_IsLineDetect = 1;
if(2 == IsLine)
ht->_IsLineDetect = 2;
}
//哈希表的插入
void HashTableInsert(HT *ht, DataType data)
{
assert(ht);
int times = 0;
if (N == ht->_totle)
{
printf("该哈希表已满,无法插入\n");
return;
}
//计算地址
int addr = HashTableAddr(data);
//如果是线性探测
if(1 == ht->_IsLineDetect)
addr = IsLineDetect(ht, addr);
//如果是二次探测
if (2 == ht->_IsLineDetect)
addr = IsLineDetect2(ht, addr);
//地址已合法,可以插入
ht->_arr[addr]._data = data;
ht->_arr[addr].State = EXIST;
++ht->_size;
++ht->_totle;
}
//哈希表的删除
void HashTableDelete(HT* ht, DataType data)
{
int del = 0;
assert(ht);
if (0 == ht->_size)
{
printf("该哈希表为空,不能删除\n");
return;
}
del = HashTableFind(ht, data);
ht->_arr[del].State = DELET;
ht->_size--;
}
//查找哈希表中某个元素
int HashTableFind(HT *ht, DataType data)
{
assert(ht);
if (0 == ht->_size)
{
printf("哈希表为空,则该元素不在此哈希表中\n");
return -1;
}
依次遍历
//int i = 0;
//for (; i < N; ++i)
//{
// if (EXIST == ht->_arr[i].State && data == ht->_arr[i]._data)
// {
// printf("该元素的下标为:%d\n", i);
// return i;
// }
//}
//printf("该元素不在此哈希表中\n");
//return -1;
int addr = HashTableAddr(data);
int sign = addr; //标志初始位置
//线性探测
if (1 == ht->_IsLineDetect)
{
while (EMPTY != ht->_arr[addr].State)
{
//如果该位置的状态是存在,并且数据相等则找到了
if (EXIST == ht->_arr[addr].State && data == ht->_arr[addr]._data)
{
printf("该数据在此哈希表中,下标为:%d\n", addr);
return addr;
}
++addr;
if (addr >= N)
addr = 0;
if (sign == addr) //如果找了一遍没找到,则不存在
{
printf("该数据不在次哈希表中\n");
return -1;
}
}
printf("该数据不在次哈希表中\n");
return -1;
}
//二次探测
int times = 0;
if(2 == ht->_IsLineDetect)
{
while (EMPTY != ht->_arr[addr].State)
{
//如果该位置的状态是存在,并且数据相等则找到了
if (EXIST == ht->_arr[addr].State && data == ht->_arr[addr]._data)
{
printf("该数据在此哈希表中,下标为:%d\n", addr);
return addr;
}
//如果该位置状态为删除,则直接退出
if (DELETE == ht->_arr[addr].State)
{
printf("该数据不在次哈希表中\n");
return -1;
}
addr += times * 2 + 1;
if (addr >= N)
addr = addr % N;
times++;
if (sign == addr) //如果找了一遍没找到,则不存在
{
printf("该数据不在次哈希表中\n");
return -1;
}
}
printf("该数据不在次哈希表中\n");
return -1;
}
}
//计算哈希表中元素的个数
int HashTableSize(HT *ht)
{
assert(ht);
return ht->_size;
}
//判断哈希表是否为空
int HashTableEmpty(HT *ht)
{
assert(ht);
return ht->_size;
}
test.c
#include"HashTable.h"
void test()
{
HashTable ht;
HashTableInit(&ht, 2);
HashTableInsert(&ht, 13);
HashTableInsert(&ht, 23);
HashTableInsert(&ht, 16);
HashTableInsert(&ht, 26);
HashTableInsert(&ht, 19);
HashTableInsert(&ht, 29);
HashTableFind(&ht, 26);
HashTableFind(&ht, 5);
HashTableDelete(&ht, 16);
HashTableFind(&ht, 16);
printf("该哈希表中的元素个数为:%d\n", HashTableSize(&ht));
int ret = HashTableEmpty(&ht);
if (0 == ret)
printf("该哈希表为空\n");
else
printf("该哈希表不为空\n");
}
int main()
{
test();
system("pause");
return 0;
}