Hash(哈希/散列)表中冲突处理及命中计算

前言

  本片博客主要讲的是哈希表中简单的冲突处理的方法,以及命中率计算。原理方面基本没有讲解,基本就讲个方法,主要用于知识记录以及帮助一些刷题玩家浏览。

  简而言之,不讲技术,只讲方法。

引言

  写这篇博客的契机是在刷pat甲级题遇到了一道写哈希的题目,结果英文太次被欺负了。之后靠翻译读懂题目,结果被命中率给坑了,遥想起以前打比赛好像也被这个坑过,愤懑不平来写博。

  相关参考:https://blog.csdn.net/xyzbaihaiping/article/details/51607770

  相关题目:PAT (Advanced Level) Practice -- 1145 Hashing - Average Search Time (25 分)

前缀知识

  hash:音译哈希,意译散列,用于在规定大小的表中,快速插入和查找数据。

  构造哈希表的几种方法:
    1.直接定址法(取关键字的某个线性函数为哈希地址)
    2.除留余数法(取关键值被某个不大于散列表长m的数p除后的所得的余数为散列地址)
    3.平方取中法(关键字平方后,取中间一段数字)
     4.折叠法
    5.随机数法
    6.数学分析法
  常用方法是 直接定址法除留余数法
  一般做的题目都是喜欢自己写哈希的,简单而且好控制 因为题目要求。直接定址题目一般会给你方法的,在此讲余数法。

冲突处理

  冲突处理分成大类和小类,大类为开散列方法( open hashing,也称为拉链法,separate chaining )  闭散列方法( closed hashing,也称为开地址方法,open addressing )

  开散列我没写过,不提了,以后被坑可能会补。

  闭散列最常用的两个:线性探测(Linear probing)  二次探测(Quadratic probing)。(英文苦逼注意下,沙雕博主看不懂二次和探测的英文,结果卡题卡半天啊。看下混个眼熟)

  一、线性探测

    key = Hash(key) + 1

    key = Hash(key) + 2    以此类推。说明:hash(key)就是构造哈希的方法。

   如果是余数法,而且是来回探测的话:

    key =(Hash(key) + 1) % size

    key =(Hash(key) - 2 + size) % size     以此类推

   探测系数一直到size为止,那么也就是直到表满都放得下

  二、二次探测

    key = Hash(key) + 1*1

    key = Hash(key) + 2*2    以此类推

   如果是余数法,而且是来回探测的话:

    key =(Hash(key) + 1*1) % size

    key =(Hash(key) - 2*2 + size) % size     以此类推

   探测系数一直到size为止,如果路上查到的key都有数据的话,那么这个数据无法放入(题目特殊要求按题目定)

命中计算

  其实没什么难度,主要是被坑了不爽无能狂怒rua

  按构表法和冲突处理法进行查找,没进行一次查找,查找次数+1,如果当前的查找那个位置是空的话,代表找不到,那么结束

  如果冲突系数一直到size还没找到,那么超过size的那次判断也算作一次查找  

//msize是表的容量
for(j=0;j) {
    cnt++;
        //没有找到或者找到了都算结束了
    if(a[(x%msize + j*j) % msize] == 0) break;
    if(a[(x%msize + j*j) % msize] == x) break;
}
//冲突处理完的这个判断,也算一次查找
if(j == msize) cnt++;
//除以总数,算平均值
printf("%.1lf\n",cnt*1.0/m);

  其实这个命中率并没有什么明确的规定,在此提出只是表示 “啊,这么狗的命中率也有啊” 的感想。刷题时(不管是比赛还是测试),都要随机应变,依靠样例去猜出题人的想法,今天可能出界+1,明天就可能没查到不算一次查询。

后记

  感谢看到这么后面,这算是很胡闹的博文。比赛中技术知识只决定七成的结果,剩下的英语水平、码力和运气占的更多

  看到最近icpc徐州站和去年的青岛站有感而发

你可能感兴趣的:(Hash(哈希/散列)表中冲突处理及命中计算)