散列表
散列表是实现字典操作的一种有效数据结构。散列查找在实际的应用中性能很出色。
散列,即将数据按照某种方法分散排列。而将数据关键字映射到储存空间的这种方法称为散列函数(hash function)。在散列过程中,由于储存空间的限制(分配给散列表空间的限制),经常会出现数据散列的冲突 (collission),即两个或多个数据被放置的位置相同。而开放地寻址法和链接寻址法则是解决冲突的两种方法。
实现中,散列表多以数组和链表的形式出现。开放寻址法直接在数组中寻址,若寻得地址与已散列数据地址重叠,则检测该地址的相邻位置,若该地址无数据占用,则将待插入数据放置在此处,若该相邻位置也已有数据,则检测该相邻位置的相邻位置,按此法依次寻找直至找到空闲位置。链接寻址法则在遇到冲突时采用链表来解决。该方法在第一次寻得的地址处链接一个链表,并将所有被映射到该地址的数据按顺序插入链表。间接地,通过在链表上的插入与搜索,来实现散列表的插入与搜索。
以下为开放寻址法的一种hash table实现:
#include <stdio.h>
//=====hash table (open addressing)=======//
#define NIL 0
#define BUFFER_SIZE 20
#define ERR -1
int A[BUFFER_SIZE] = {NIL};
/* hash function,take division hash function as implementation*/
int h (int key, int i)
{
//default divisor 10
static int d = 10;
return key % d + i;
}
/* assume array size is larger than
variable j inside function */
int hash_insert (int* A, int k)
{
int i = 0;
do
{
int j = h (k, i);
if (A[j] == NIL)
{
A[j] = k;
return j;
}
else ++i;
}
while (i != BUFFER_SIZE);
return ERR;
}
/* similar with function--hash_insert () */
int hash_search (int* A, int key)
{
int i = 0;
int j;
do
{
j = h (key, i);
if (A[j] == key) return j;
else ++i;
}
while (A[j] != NIL && j != BUFFER_SIZE);
return NIL;
}
代码非常简单,在此不再赘述。
因链接地址法,只是在开放地址法的基础上使用了链表,故在此也
不再给出代码,开放地址法的图形表示可以参见桶排序的图形。参见
算法导论,或参考此处博文 introduce to algorithm—–pseudo code to C/C++ code;
事实上,散列函数在散列表中扮演者非常重要的作用,可以说散列函
数决定了散列表实现的质量。散列函数又分除法散列、乘法散列,探查(probe)、二次探查,完全散列函数等都是与散列函数有关的内容
细文请自行参见算法导论