《iOS面试题整理》 - 哈希表

哈希表, 也叫散列表, 是数组的一种扩展
把关键字或者键转换为数组下标的方法叫做散列函数
散列函数计算得到的值也叫做散列值或hash值

散列冲突

解决散列冲突的方法: 开放寻址法 和 链表法

开放寻址法

  1. 线性探测
    如果数据经过散列函数散列后, 存储位置被占用了, 我们就从当前位置开始, 依
    次往后查找, 看是否有空闲位置, 直到找到为止

    对于删除操作, 不能单纯地把要删除的元素置位空, 因为如果这个空闲的位置是
    后来删除的, 就会导致原来的查找算法失效, 本来存在的数据, 会认定为不存在,
    这个问题的话, 我们可以将删除的元素特殊标记为 deleted, 遇到标记 deleted的
    空间, 并不是停下来, 而是继续往下探测

    所以, 散列表插入的数据越来越多时, 散列冲突发生的可能性就会越来越大, 空
    闲的位置会越来越少, 线性探测的时间会越来越久. 极端情况下, 需要探测整个
    散列表, 所以最坏情况下的时间复杂度是 O(n)

  2. 二次探测
    线性探测每次探测的步长是 1, hash(key) + 0, hash(key) + 1, 二次探测的步长变为二次方, hash(key) + 0, hash(key) + 1^2, hash(key) + 2^2

  3. 双重散列
    不仅使用一个散列函数, 还要使用一组散列函数 hash1(key), hash2(key), hash3(key).... 优先使用第一个函数, 如果有冲突, 就用第二个散列函数

不管哪种探测方法, 散列表中空闲位置不多的时候, 散列冲突概率会大大提高。 需要尽可能保证散列表的操作效率, 一般情况下, 保证一定比例的空闲槽位。用装载因子来表示空位的多少

    装载因子 = 填入表的元素个数 / 散列表的长度

链表法

所有散列值相同的元素都放到相同槽位对应的链表中, 插入的时候只需要通过散列函数计算出对应的槽位, 将其插入到对应的链表中即可, 所以插入的时间复杂度是 O(1)

你可能感兴趣的:(《iOS面试题整理》 - 哈希表)