基于线性探测法的散列表

#include <stdio.h>

//基于线性探测法的散列表

//使用线性探测解决键冲突问题,核心思想就是利用数组空位,当使用
//哈希函数计算出数组索引后,开始检测该索引位置是否已经被使用,如
//果已经使用,则索引向后递增(如果超出数组索引,则需要进行回绕到
//数组起始索引),直到找到空位为止,或者数组空间已全部被使用,无
//法再扩冲,由于这里利用的是数组空间,所以通常情况下,需要该数组
//支持动态调整数组空间功能,当前简化了这步流程,仅使用静态数组进
//行分析。

#define TEST_CASE  (1)

#define MAX_HASH_ENTRY  5

typedef struct
{
    int used;
    int key;
    int val;
} HASH_ENTRY;

HASH_ENTRY hashTableEntrys[MAX_HASH_ENTRY] = {0};
int g_hashTableEntryCount = 0;

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

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

//新增条目
//1 当前不支持动态调整数组空间,所以需要检测溢出的隐患
//2 进行数组空位查找
void put(int key, int val)
{
    int index = hashIndex(key);

    if ( g_hashTableEntryCount >= MAX_HASH_ENTRY )
    {
        printf("don't put, array full.\r\n");
        return; 
    }

    while ( hashTableEntrys[index].used )
    {
        index = (index + 1) % MAX_HASH_ENTRY;
    }

    hashTableEntrys[index].used = 1;
    hashTableEntrys[index].key = key;
    hashTableEntrys[index].val = val;
    g_hashTableEntryCount++;
}

//查找
//这里有3种情况会退出循环
//1 没有对应的空位了,即没有找到需要的数组
//2 有对应的空位,但键值不是要查找的
//3 防止数组出现满的情况,这时候需要进行环绕检测,避免死循环
int get(int key)
{
    int val = -1;
    int index = hashIndex(key);
    int curGetIndex = index;

    while ( hashTableEntrys[index].used )
    {
        if ( curGetIndex == index )
        {
            break; 
        }

        if ( hashTableEntrys[index].key == key  )
        {
            val = hashTableEntrys[index].val;
            break; 
        }

        index = (index + 1) % MAX_HASH_ENTRY;
    }

    return val;
}

//删除
//线性探测法由于在进行查找时,遇到空位则停止,所以在进行删除
//时,后面数据的问题,比如当前要删除hashKey = 3,当删除第一个
//条目时,第一个位置出现了空洞,此时需要将后面项全部删除并重
//新插入,否则后面数据将无法访问。
// -------------------------
// |3|3|3|3| | | | | | | | |
// -------------------------
int delete(int key)
{
    int find = 0;
    int index = hashIndex(key);

    while ( hashTableEntrys[index].used )
    {
        if ( hashTableEntrys[index].key == key )
        {
            find = 1;
            break; 
        }

        index = (index + 1) % MAX_HASH_ENTRY;
    }

    if ( find )
    {
        int curDeleteIndex = index;
        hashTableEntrys[index].used = 0;
        g_hashTableEntryCount--;

        index = (index + 1) % MAX_HASH_ENTRY;
        while ( hashTableEntrys[index].used && (curDeleteIndex != index) )
        {
            put(hashTableEntrys[index].key, hashTableEntrys[index].val);

            hashTableEntrys[index].used = 0;
            g_hashTableEntryCount--;

            index = (index + 1) % MAX_HASH_ENTRY;
        }
    }

    return find ? 0 : -1 ;
}

void testCase0()
{
    put(1, 1);
    put(2, 2);
    put(3, 3);
    put(4, 4);
    put(5, 5);
    put(6, 6);
    put(7, 7);

    printf("find key %d, val %d\r\n", 3, get(3));
    printf("find key %d, val %d\r\n", 7, get(7));
}

void testCase1()
{
    put(3, 3);
    put(3, 3);
    put(3, 3);
    put(3, 3);
    put(3, 3);
    put(3, 3);
    put(3, 3);

    delete(3);
    delete(3);
    delete(3);
    delete(3);
    delete(3);
    delete(3);
    delete(3);

    printf("find key %d, val %d\r\n", 3, get(3));
}

int main()
{
    printf("max hashTable entry %d\r\n", MAX_HASH_ENTRY);

    switch ( TEST_CASE )
    {
        case 0: testCase0(); break;
        case 1: testCase1(); break;
        default: break;
    }

    return 0;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值