首先是需要定义一个散列表的结构以及一些相关的常数。其中HashTable就是散列表结构。结构当中的elem为一个动态数组。
#define SUCCESS 1#define UNSUCCESS 0/* 定义散列表长为数组的长度 */#define HASHSIZE 12#define NULLKEY -32768typedef 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 OK;}
为了插入时计算地址,我们需要定义散列函数,散列函数可以根据不同情况更改算法。
/* 散列函数 */int Hash(int key){/* 除留余数法 */return key % m;}
初始化完成后,我们可以对散列表进行插入操作。假设我们插入的关键字集合就是前面的
{12,67,56,16,25,37,22,29,15,47,48,34}。
/* 插入关键字进散列表 */void InsertHash(HashTable *H, int key){/* 求散列地址 */int addr = Hash(key);/* 如果不为空,则冲突 */while (H->elem[addr] != NULLKEY)/* 开放定址法的线性探测 */addr = (addr + 1) % m;/* 直到有空位后插入关键字 */H->elem[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;}
查找的代码与插入的代码非常类似,只需做一个不存在关键字的判断而已。
