查找有两种方式,比较式查找和计算式查找,而计算式查找则通过哈希表来实现。给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数;更通俗来说,哈希表通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这里用除留余数法来构造哈希表和开放地址法中的线性探测再散列来处理不同关键字通过哈希函数映射到同一地址的冲突。
1、除留余数法:取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址。即 H(key) = key MOD p,p<=m。
2、线性探测再散列:Hi=(H(key) + di) MOD m,i=1,2,…,k(k<=m-1),其中H(key)为散列函数,m为散列表长,di=1,2,3,…,m-1
具体程序如下
#include<stdio.h>
#define N 13
//哈希函数(除留余数法)
int HS(int key){
return key%N;
}
//在哈希表中查找key,若找到返回其所在的位置,否则将key插入哈希表或表满则返回-1
int thread(int key,int m,int addr[]){
int i,j;
i=HS(i);//计算key的哈希地址
if(addr[i]==key){//若key在哈希表中则返回所在位置
return i;
}
i--;
j=(i+1)%m;//线性探测再散列处理冲突
while(addr[j]!=key&&addr[j]!=0){
if(j!=i){
j=(j+1)%m;
}else{
return -1;//表满
}
}
if(addr[j]==key) return j;
if(addr[j]==0){
addr[j]=key;//若找到空位置则插入
return j;
}
}
int main(){
int i,j,m,n,num[N],addr[N];
printf("输入元素的个数:");
scanf("%d",&n);
printf("输入各元素值,用空格隔开:");
for(i=0;i<n;i++){
scanf("%d",&num[i]);
}
printf("\n");
for(i=0;i<N;i++){
addr[i]=0;
}
for(i=0;i<n;i++){
thread(num[i],N,addr);
}
printf("所得哈希表如下所示:\n");
for(i=0;i<N;i++){
printf("%5d",i);
}
printf("\n");
for(i=0;i<N;i++){
if(addr[i]!=0){
printf("%5d",addr[i]);
}else{
printf("%5c",' ');
}
}
printf("\n\n");
printf("输入要查找或要插入的元素值:");
scanf("%d",&j);
m=thread(j,N,addr);
printf("%d所在的位置是:%d\n",j,m);
}