哈希表(散列表)
哈希表中元素是由哈希函数确定的。将数据元素的关键字key作为自变量,通过一定的函数关系H(称为哈希函数),计算出的值,即为该元素的存储地址。其优点是:运算速度快;缺点是:基于数组、难于扩展,不可遍历。
构造均匀的哈希函数
使H(key)均匀分布在哈希表中,以提高地址计算的速度。
构造哈希函数的方法:直接定址法,除留余数法,数字分析法,平法折中法,折叠法,随机数法等。
处理冲突
冲突是指在哈希表中,不同的关键字值对应到同一个存储位置的现象。即存在K1≠K2,但H(K1)=H(K2)。再均匀的哈希函数都只能可减少冲突,但不可能避免冲突。
发生冲突后,必须解决,即必须寻找下一个可用地址。
解决冲突的方法:开放地址法(包括线性探测,二次探测,随机探测),链地址法,再哈希法,建立公共溢出区等。
//除留余数法 + 开放定址法
#define SUCCESS 1
#define UNSUCCESS 0
#define HASHSIZE 12 /*定义散列表长为数组的长度*/
#define NULLKEY -32768
typedef struct
{
int *elem; /*数据元素存储基址,动态分配数组*/
int count; /*当前数据元素个数*/
} HashTable;
int m = 0; /*散列表表长,全局变量*/
/*初始化散列表*/
Status 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 SUCCESS ;
}
/* 散列函数 */
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->e1em[addr] = key; /*直到有空位后插入关键字*/
}
/*散列表查找关键字*/
Status 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 UNSUCCESS; /*则说明关键字不存在*/
}
return SUCCESS;
}