首先是需要定义一个散列表的结构以及一些相关的常数。其中HashTable就是散列表结构。结构当中的elem为一个动态数组。

    1. #define SUCCESS 1
    2. #define UNSUCCESS 0
    3. /* 定义散列表长为数组的长度 */
    4. #define HASHSIZE 12
    5. #define NULLKEY -32768
    6. typedef struct{
    7. /* 数据元素存储基址,动态分配数组 */
    8. int *elem;
    9. /* 当前数据元素个数 */
    10. int count;
    11. } HashTable;
    12. /* 散列表表长,全局变量 */
    13. int m = 0;

    有了结构的定义,我们可以对散列表进行初始化。

    1. /* 初始化散列表 */
    2. Status InitHashTable(HashTable *H){
    3. int i;
    4. m = HASHSIZE;
    5. H->count = m;
    6. H->elem = (int *)malloc(m * sizeof(int));
    7. for (i = 0; i < m; i++)
    8. H->elem[i] = NULLKEY;
    9. return OK;
    10. }

    为了插入时计算地址,我们需要定义散列函数,散列函数可以根据不同情况更改算法。

    1. /* 散列函数 */
    2. int Hash(int key){
    3. /* 除留余数法 */
    4. return key % m;
    5. }

    初始化完成后,我们可以对散列表进行插入操作。假设我们插入的关键字集合就是前面的
    {12,67,56,16,25,37,22,29,15,47,48,34}。

    1. /* 插入关键字进散列表 */
    2. void InsertHash(HashTable *H, int key){
    3. /* 求散列地址 */
    4. int addr = Hash(key);
    5. /* 如果不为空,则冲突 */
    6. while (H->elem[addr] != NULLKEY)
    7. /* 开放定址法的线性探测 */
    8. addr = (addr + 1) % m;
    9. /* 直到有空位后插入关键字 */
    10. H->elem[addr] = key;
    11. }

    代码中插入关键字时,首先算出散列地址,如果当前地址不为空关键字,则说明有冲突。此时我们应用开放定址法的线性探测进行重新寻址,此处也可更改为链地址法等其他解决冲突的办法。

    散列表存在后,我们在需要时就可以通过散列表查找要的记录。

    1. /* 散列表查找关键字 */
    2. Status SearchHash(HashTable H, int key, int *addr){
    3. /* 求散列地址 */
    4. *addr = Hash(key);
    5. /* 如果不为空,则冲突 */
    6. while (H.elem[*addr] != key){
    7. /* 开放定址法的线性探测 */
    8. *addr = (*addr + 1) % m;
    9. if (H.elem[*addr] == NULLKEY || *addr == Hash(key)){
    10. /* 如果循环回到原点则说明关键字不存在 */
    11. return UNSUCCESS;
    12. }
    13. }
    14. return SUCCESS;
    15. }

    查找的代码与插入的代码非常类似,只需做一个不存在关键字的判断而已。