[C]哈希表(HashTable)设计实现

哈希表是一种快速访问数据结构,通过哈希函数将关键码映射到数组位置。拉链法是解决哈希碰撞的常用方法,通过在冲突位置建立链表。负载因子影响性能,标准库通常设定阈值为0.75。哈希函数设计要减少碰撞并保持高效,如除法散列法。哈希表接口包括插入、查找、删除和释放内存。本文提供了一个基于拉链法的哈希表设计示例。
摘要由CSDN通过智能技术生成
  • HashTable

    HashTable(散列表,又称哈希表),是根据关键码值(key, value)来进行快速访问的一种数据结构。它通过把关键码值(key)映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数(哈希函数),存放记录的数组叫做散列表。[摘自百度百科]

    更通俗来讲,哈希表就是我们预先开辟的一个数组空间,它存储了我们的关键码值,但是与数组不同的是,哈希表的下标index是由键key值通过哈希函数计算得到的。由此也可以看出不同的关键码可能对应相同的位置,这就是哈希碰撞

  • 哈希碰撞:不同的关键码对应相同的位置,常见解决方法有散列法拉链法

  1. 散列法:又分开放寻址法和再散列法(按照不同的哈希函数再次计算哈希值)
  2. 拉链法:在产生哈希碰撞的位置建立链表,所有的冲突值都链入链表(常用方法,后文示例也是基于拉链法)
    哈希碰撞主要与负载因子和哈希函数有关,良好的哈希函数能够有效地降低哈希碰撞并提升插入和查找数据的性能。
  • 负载因子:哈希表中已有元素个数与哈希表长度的比值。基于性能和空间的选择,在JDK标准库中将负载因子阈值定为0.75

  • 哈希函数:关键码到哈希表的映射关系函数。哈希函数是非常重要的,对于哈希函数的设计需要考虑一下两点:
    1.尽可能降低哈希碰撞,计算出的哈希值越分散越好;
    2.因为是高频操作,所以算法要高效

    常见的哈希函数有:
    1.直接定值法

    Hash(key) = a·key + b
    

    该方法不会产生哈希碰撞,但是空间复杂度较高,这里不再做具体介绍。
    2. 除法散列法

    Hash(key) = key % base
    

    base代表哈希表的长度。这是一种最为常用的哈希函数。对于哈希表长度我们经常取2的幂次方,因为key % 2^n = key & (2^n - 1),而&计算相比取模操作要快很多。如果要考虑key是负数的情况,则可以采用如下哈希函数:

    Hash(key) = (key & 0x7fffffff) & (base - 1)
    

    3.斐波那契散列法

    Hash(key) = (key * base) >> 28
    

    对于16位整数base取40503;对于32位整数base取2654435769;对于64位整数,base取11400714819323198485

  • 扩容:当哈希表的元素数量逐渐增加,如果不对增加哈希表长度,哈希表将退化为链表,此时哈希表的性能将会降低。本文主要介绍基于除法散列法的扩容策略:

    1.在元素个数 >= 哈希长度 * 负载因子时对哈希表进行扩容,扩容后的长度为上次的2倍
    2.扩容后需要对已存储数据重新计算哈希值,并放入新的哈希表中

  • 一个哈希表应有以下几个接口:

    put(key, value):新增数据,如果哈希表中已有key存在,则覆盖原来的数据
    get(key):查找数据
    remove(key):删除数据
    free():释放内存

为了更好的展示哈希表设计原理,本文将以C语言来完成设计。

// 定义链表,存放key value
typedef struct ListNode_ {
   
    int key;
    int value;
    struct ListNode_* next;
} __ListNode;

void ListPush(__ListNode* head, int key, int value) {
   
    __ListNode* node = (__ListNode*)malloc(sizeof(__ListNode));
    node->key = key;
    node->value = value;
    node->next 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值