哈希表(散列表)是直接通过关键字key得到要查找的记录的内存存储位置。
散列技术是在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使得每个关键字key对应一个存储位置f(key)。
采用散列技术将记录存储在一块连续的存储空间中,这块连续的存储空间称为散列表或者哈希表。
整个散列过程分为两步:
1.在存储时,通过散列函数计算记录的散列地址,并按此地址存储该记录。
2.当查找记录时,通过同样的散列函数计算记录的散列地址,按此地址方位记录。
因此散列技术既是一种存储方法也是一种查找方法,数据元素之间不存在逻辑关系。
散列技术最合适的问题是查找与给定值相等的记录。
散列函数设计的两个原则是计算简单、散列地址分布均匀。
最长用的方法是除留余数法,f(key)=key mod p(p小于等于散列表的长度m)。
但散列函数可能会造成冲突,即两个不同的记录求得的散列地址一样,解决散列冲突最常用的方法为开放定址法。一旦发生冲突,就去寻找下一个散列地址,只要散列表足够大,空的散列地址总能找到。
以下程序在DEV C++中调试运行通过。
#include<stdio.h>
#include<stdlib.h>
#define HASHSIZE 12
#define NULLKEY -32768
typedef struct
{
int *elem;
int count;
}HashTable;
int m=0;
//初始化散列表
int InitHashTable(HashTable *H)
{
int i;
m=HASHSIZE;
H->count=m;
H->elem=(int*)malloc(m*sizeof(int));
for(i=0;i<m;i++)
H->elem[i]=NULLKEY;
return 1;
}
//散列函数
int Hash(int key)
{
return key%m;
}
//插入关键字进入散列表
void InsertHash(HashTable *H,int key)
{
int addr=Hash(key);
while(H->elem[addr]!=NULLKEY)
addr=(addr+1)%m;
H->elem[addr]=key;
}
//散列表查找关键字
int SearchHash(HashTable H,int key,int *addr)
{
*addr=Hash(key);
while(H.elem[*addr]!=key)
{
*addr=(*addr+1)%m;
if(H.elem[*addr]==NULLKEY||*addr==Hash(key))
{
return -1;
}
}
return *addr;
}
int main()
{
int a[12]={12,67,56,16,25,37,22,29,15,47,48,34};
HashTable H;
int i;
InitHashTable(&H);
for(i=0;i<m;i++)
InsertHash(&H,a[i]);
printf("插入之后的哈希表为:");
for(i=0;i<m;i++)
printf("%d,",H.elem[i]);
int addr,j;
j=SearchHash(H,a[5],&addr);
printf("搜索到a[5]的地址是:%d",j);
}
运行结果如图所示。
如果没有冲突,哈希表查找算法的时间复杂度为O(1)。