一、哈希函数
数字关键词:h(Key)=Key mod TableSize
int Hash(const ElementType Key,int TableSize)
{
return Key%TableSize;
}
二、开放地址法声明
//开放地址法的类型声明
#define MaxTableSize 10000//允许开辟的最大散列表的长度
typedef int ElementType;//关键词类型
typedef int Index;//散列地址类型
typedef Index Position;//数据所在位置类型
//散列单元状态类型:合法元素,空元素,已删除元素
typedef enum{
Legitimate,Empty,Deleted
}EntryType;
typedef struct HashEntry Cell;//散列表单元类型
struct HashEntry{
ElementType Data;//存放元素
EntryType Info;//单元状态
};
typedef struct TblNode *HashTable;//散列表类型
struct TblNode{
int TableSize;//表的最大长度
Cell *Cells;//存放散列单元数据的数组
};
三、开放地址法的初始化
int Prime(int N)
{
//返回小于等于N的最大素数
int i,p;
if(N>=1&&N<=3)p=N;
else p=(N%2)?N:N-1;//取奇数
while(p<=N&&p>4){
for(i=(int)sqrt(p);i>2;i--)
if(!(p%i))break;//p不是素数
if(i==2)break;//p是素数
else p-=2;
}
return p;
}
HashTable CreateTable(int TableSize)
{
HashTable H;
int i;
H=(HashTable)malloc(sizeof(struct TblNode));
//保证散列表的最大长度为素数
H->TableSize =Prime(TableSize);
H->Cells =(Cell *)malloc(sizeof(Cell)*H->TableSize);
for(i=0;i<H->TableSize ;i++)
H->Cells[i].Info =Empty;//都置为“空单元”
return H;
}
四、平方探测法的查找函数
过程:
1.首先调用Hash函数计算地址,确定关键词所在的散列表的地址
2.查找位置
Position Find(HashTable H,ElementType Key)
{
Position CurrentPos,NewPos;
int CNum=0;//记录冲突次数
NewPos= CurrentPos=Hash(Key,H->TableSize );
//当该位置的单元非空,并且不是要找的元素时,发生冲突
while(H->Cells[NewPos].Info!=Empty&&H->Cells[NewPos].Data !=Key){
//统计一次冲突,并判断奇偶性
CNum++;
if(CNum%2){//奇数次冲突
//增量为+[(CNum+1)/2]^2;
NewPos=CurrentPos+((CNum+1)/2)*((CNum+1)/2);
if(NewPos>=H->TableSize )
NewPos=NewPos%H->TableSize ;//调整溢出的地址为合法地址
} else{//偶数次冲突
//增量为-(CNum/2)^2
NewPos=CurrentPos-(CNum/2)*(CNum/2);
while(NewPos<0)
NewPos+=H->TableSize ;//调整溢出的地址为合法地址
}
} //结束while循环
return NewPos;
}
五、平方探测法的插入函数
bool Insert(HashTable H,ElementType Key)
{
Position Pos=Find(H,Key);//先检查Key是否存在
if(H->Cells[Pos].Info !=Legitimate){
//如果这个单元没有被占用,那么久可以插入Key
H->Cells[Pos].Data =Key;
H->Cells[Pos].Info =Legitimate;
return true;
} else{
printf("键值已经存在\n");
return false;
}
}
六、完整代码
//哈希函数——位移映射
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<math.h>
//开放地址法的类型声明
#define MaxTableSize 10000//允许开辟的最大散列表的长度
typedef int ElementType;//关键词类型
typedef int Index;//散列地址类型
typedef Index Position;//数据所在位置类型
//散列单元状态类型:合法元素,空元素,已删除元素
typedef enum{
Legitimate,Empty,Deleted
}EntryType;
typedef struct HashEntry Cell;//散列表单元类型
struct HashEntry{
ElementType Data;//存放元素
EntryType Info;//单元状态
};
typedef struct TblNode *HashTable;//散列表类型
struct TblNode{
int TableSize;//表的最大长度
Cell *Cells;//存放散列单元数据的数组
};
//哈希函数
//数字:h(Key)=Key mod TableSize
int Hash(const ElementType Key,int TableSize)
{
return Key%TableSize;
}
int Prime(int N)
{
//返回小于等于N的最大素数
int i,p;
if(N>=1&&N<=3)p=N;
else p=(N%2)?N:N-1;//取奇数
while(p<=N&&p>4){
for(i=(int)sqrt(p);i>2;i--)
if(!(p%i))break;//p不是素数
if(i==2)break;//p是素数
else p-=2;
}
return p;
}
HashTable CreateTable(int TableSize)
{
HashTable H;
int i;
H=(HashTable)malloc(sizeof(struct TblNode));
//保证散列表的最大长度为素数
H->TableSize =Prime(TableSize);
H->Cells =(Cell *)malloc(sizeof(Cell)*H->TableSize);
for(i=0;i<H->TableSize ;i++)
H->Cells[i].Info =Empty;//都置为“空单元”
return H;
}
/*----------创建结束-------------*/
/*-------------平方探测法---------------*/
/*-----------查找----------*/
/*
过程:
1.首先调用Hash函数计算地址,确定关键词所在的散列表的地址
2.查找位置
*/
Position Find(HashTable H,ElementType Key)
{
Position CurrentPos,NewPos;
int CNum=0;//记录冲突次数
NewPos= CurrentPos=Hash(Key,H->TableSize );
//当该位置的单元非空,并且不是要找的元素时,发生冲突
while(H->Cells[NewPos].Info!=Empty&&H->Cells[NewPos].Data !=Key){
//统计一次冲突,并判断奇偶性
CNum++;
if(CNum%2){//奇数次冲突
//增量为+[(CNum+1)/2]^2;
NewPos=CurrentPos+((CNum+1)/2)*((CNum+1)/2);
if(NewPos>=H->TableSize )
NewPos=NewPos%H->TableSize ;//调整溢出的地址为合法地址
} else{//偶数次冲突
//增量为-(CNum/2)^2
NewPos=CurrentPos-(CNum/2)*(CNum/2);
while(NewPos<0)
NewPos+=H->TableSize ;//调整溢出的地址为合法地址
}
} //结束while循环
return NewPos;
}
/*-----------查找结束----------*/
/*-----------插入----------*/
bool Insert(HashTable H,ElementType Key)
{
Position Pos=Find(H,Key);//先检查Key是否存在
if(H->Cells[Pos].Info !=Legitimate){
//如果这个单元没有被占用,那么久可以插入Key
H->Cells[Pos].Data =Key;
H->Cells[Pos].Info =Legitimate;
return true;
} else{
printf("键值已经存在\n");
return false;
}
}
/*-----------插入结束----------*/
int main()
{
int TableSize,i;
int N;
ElementType Key;
printf("请输入散列表长度:");
scanf("%d",&TableSize);
//创建
HashTable H=CreateTable(TableSize);
//插入
printf("请输入关键词个数:");
scanf("%d",&N);
printf("请输入%d个关键词:",N);
for(i=0;i<N;i++){
scanf("%d",&Key);
Insert(H,Key);
}
//查找
printf("请输入需要查找的关键词个数:");
scanf("%d",&N);
printf("请输入%d需要查找的关键词:",N);
for(i=0;i<N;i++){
scanf("%d",&Key);
Position p=Find(H,Key);
printf("关键词%d在散列表中的位置为:%d\n",Key,p);
}
return 0;
}