基于拉链法的散列表

#include <stdio.h>

//基于拉链法的散列表
//散列表通常一个难点就是出现键冲突后,如果进行冲突解决,
//基于拉链法的散列表给每个键分配一个链表,当出现键冲突时,
//将冲突键的条目项都挂接到一个链表下,从而解决了键冲突问题。

#define MAX_HASH_ARRAY  50

typedef struct _HASH_NODE
{
    int                 key;
    int                 val;
    struct _HASH_NODE*  next;
} HASH_NODE;

//这里采用了拉链法解决链冲突问题,当使用哈希函数计算,出现了相
//同KEY时,将相同项存储到一个链表中。
HASH_NODE* hashTable[MAX_HASH_ARRAY] = {0};

//正整数类型的KEY的散列函数
//通常采用除留余法,这里通过对KEY进行求余,使得KEY分布在hashTable
//的数组中,同时为了减少键冲突,除数通常选择为素数,比如当前示例
//选择为97
int hashFunctionForInt(int key)
{
    // M 通常为素数
    //hashKey = key % M
    int hashKey = key % 97; 
    return hashKey;
}

//字符串类型的KEY的散列函数
//这里也采用了除留余法
int hashFunctionForStr(char *string)
{
    int hashKey = 0;
    int i = 0;

    for ( i = 0; i < strlen(string); i++ )
    {
        // R 在这里相当于将字符串当作一个N位的R进制值,比如这里
        // 取R值为10,假设当前string为“123”,通过R的处理,相当
        // 于这个字符串输出了整数123,即100 * 1 + 10 * 2 + 3
        // M 通常为素数,这里取值为31是为了使得字符串中所有字
        // 符都能启到关键作用
        //hashkey  = (R * hashKey + string[i]) % M
        hashKey = (10 * hashKey + string[i])  % 31;
    }

    return hashKey;
}

//计算哈希表数组的索引
// 1首先算出hashKey
// 2 之后根据当前哈希表数组长度进行求余操作,避免计算出来的hashKey大于
//  数组长度,导致出现溢出
int hashIndex(int key)
{
    int hashKey = hashFunctionForInt(key);
    return hashKey % MAX_HASH_ARRAY;
}

//插入操作
//根据当前key计算出所在哈希表数组的索引,将新的条目插入到该数组索
//引的链表中
void put(int key, int val)
{
    int        index = hashIndex(key);
    HASH_NODE* pNewNode = (HASH_NODE*)malloc(sizeof(HASH_NODE));
    if ( pNewNode == NULL )
    {
        printf("failed to malloc.\r\n");
        return; 
    }

    memset(pNewNode, 0, sizeof(HASH_NODE));
    pNewNode->key = key;
    pNewNode->val = val;

    pNewNode->next = hashTable[index];
    hashTable[index] = pNewNode;
}

//查找操作
//根据当前key计算出所在的哈希表数组索引,之外遍历当前数组索引对应的
//链表,找出与当前key相同的条目,这里之所有遍历,是因为在进行hashIndex
//计算时,可能会出现不同key有相同数组索引的情况,即键冲突。
int get(int key)
{
    int val = -1;
    int index = hashIndex(key);
    HASH_NODE* pCurHashNode = hashTable[index];

    while ( pCurHashNode )
    {
        if ( pCurHashNode->key == key ) 
        {
            val = pCurHashNode->val;
            break; 
        }

        pCurHashNode = pCurHashNode->next;
    }

    return val;
}

int getChainCount(HASH_NODE* pNode)
{
    int count = 0;

    while ( pNode != NULL )
    {
        count++;
        pNode = pNode->next;
    }

    return count;
}

void showHashTable()
{
    int i = 0;

    printf("-- showHashTable ------------------------\r\n");

    for ( i = 0; i < MAX_HASH_ARRAY; i++ )
    {
        HASH_NODE* pHashNode = hashTable[i];
        int chainCount = getChainCount(pHashNode);

        if ( chainCount > 0 )
        {
            printf("chain %d(%d):\r\n", i, chainCount); 

            while (pHashNode != NULL)
            {
                printf("  key %d, val %d\r\n", pHashNode->key, pHashNode->val); 
                pHashNode = pHashNode->next;
            }
        }
    }

    printf("-----------------------------------------\r\n");
}

int main()
{
    put(3, 3);
    put(6, 6);
    put(25, 25);
    put(29, 29);
    put(17, 17);

    showHashTable();

    printf("get key %d, val %d\r\n", 14, get(14));
    printf("get key %d, val %d\r\n", 25, get(25));

    return 0;
}

阅读更多

没有更多推荐了,返回首页