前言
本片博客主要讲的是哈希表中简单的冲突处理的方法,以及命中率计算。原理方面基本没有讲解,基本就讲个方法,主要用于知识记录以及帮助一些刷题玩家浏览。
简而言之,不讲技术,只讲方法。
引言
写这篇博客的契机是在刷pat甲级题遇到了一道写哈希的题目,结果英文太次被欺负了。之后靠翻译读懂题目,结果被命中率给坑了,遥想起以前打比赛好像也被这个坑过,愤懑不平来写博。
相关参考:https://blog.csdn.net/xyzbaihaiping/article/details/51607770
相关题目:PAT (Advanced Level) Practice -- 1145 Hashing - Average Search Time (25 分)
前缀知识
hash:音译哈希,意译散列,用于在规定大小的表中,快速插入和查找数据。
冲突处理
冲突处理分成大类和小类,大类为开散列方法( 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徐州站和去年的青岛站有感而发