为什么一般hashtable的桶数会取一个素数

设有一个哈希函数
H( c ) = c % N;
当N取一个合数时,最简单的例子是取2^n,比如说取2^3=8,这时候
H( 11100(二进制) ) = H( 28 ) = 4
H( 10100(二进制) ) = H( 20 )= 4

这时候c的二进制第4位(从右向左数)就”失效”了,也就是说,无论第c的4位取什么值,都会导致H( c )的值一样.这时候c的第四位就根本不参与H( c )的运算,这样H( c )就无法完整地反映c的特性,增大了导致冲突的几率.

取其他合数时,都会不同程度的导致c的某些位”失效”,从而在一些常见应用中导致冲突.
但是取质数,基本可以保证c的每一位都参与H( c )的运算,从而在常见应用中减小冲突几率..

(个人意见:有时候不取质数效率也不会太差..但是无疑取质数之比较保险的..)

以上就是我的理解

补充一点,这里是说在常见应用中,往往有些数据会比较相近,这时候用质数比较好,比如要存放的数据是压缩的状态,比如存储一个描述当前搜索状态的表,的这时候哈希不用质数冲突机率就比较大。

如果是随机分布的整数,那么哈希模数只要取到足够大,在概率上来说都是一样的,但是这显然脱离实际应用。

你说的情况 是比较特殊的,因为选取了比较小的一个质数,当选去大质数N时,就可以仅在N进制的某一位失效,结合计算机系统的特性,N进制位表示法往往是不关键的,而常用的2^N进制比较关键,所以可以避免冲突。

其实,偶用一些大数做过测试,用来存放一个压缩为二进制的邻接矩阵,当模数足够大时,即便是合数也能有很接近质数的效果,但在某些(几十个)合数上会造成效率严重下降,所以质数是比较保险的。

你不妨自己做实验,不要去选随机整数,而要考虑一些常见应用,用质数和合数进行测试,主要考察平均装载因子,你得到的结论可能和我一样:合数绝大多数时候效果也不错,但在一部分合数上效果差得出奇,而质数几乎全部都有很好的效果。
 
我个人认为更普遍意义的理解,如果不取素数的话是会有一定危险的,危险出现在当假设所选非素数m=x*y,如果需要hash的key正好跟这个约数x存在关系就惨了,最坏情况假设都为x的倍数,那么可以想象hash的结果为:1~y,而不是1~m。但是如果选桶的大小为素数是不会有这个问题。

为什么一般hashtable的桶数会取一个素数的更多相关文章

  1. 1001 数组中和等于K的数对 1002 数塔取数问题 1003 阶乘后面0的数量 1004 n^n的末位数字 1009 数字1的数量

    1001 数组中和等于K的数对 基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题 给出一个整数K和一个无序数组A,A的元素为N个互不相同的整数,找出数组A中所有和等于K ...

  2. 51Nod 1002:数塔取数问题(DP)

    1002 数塔取数问题  基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题  收藏  关注 一个高度为N的由正整数组成的三角形,从上走到下,求经过的数字和的最大值. 每 ...

  3. Java的8种基本数据类型的内存占用字节数和取值范围

    这是8中基本类型的内存中占用字节数(取值范围是2的(字节数X8-1)次方) 1.整型 类型 存储需求 bit数 取值范围 byte 1字节 1*8 -128-127 short 2字节 2*8 -32 ...

  4. 得到List<HashTable>里面的list然后取list的某一项

    //得到List<HashTable>里面的listUnFix然后取listUnFix判断tempfix里面得值 List<Hashtable> list = new List ...

  5. 51nod 1002 数塔取值问题 dp

    动态规划 1002 数塔取数问题 1.0 秒 131,072.0 KB 5 分 1级题   一个高度为N的由正整数组成的三角形,从上走到下,求经过的数字和的最大值. 每次只能走到下一层相邻的数上,例如 ...

  6. 取一个整数a从右端开始的4~7位

    题目:取一个整数a从右端开始的4-7位. 程序分析:可以这样考虑: (1)先使a右移4位. (2)设置一个低4位全为1,其余全为0的数.可用~(~0 < <4) (3)将上面二者进行&am ...

  7. 12--c完数/最大公约数/最小公倍数/素数/回文数

    完数/最大公约数/最小公倍数/素数/回文数 2015-04-08 10:33 296人阅读 评论(0) 收藏 举报  分类: C/C++(60)  哈尔滨工业大学(8)  版权声明:本文为博主原创文章 ...

  8. java例题_32 取一个整数a从右端开始的4~7位

    1 /*32 [程序 32 左移右移] 2 题目:取一个整数 a 从右端开始的 4-7 位. 3 */ 4 5 /*分析 6 * 从右端开始的第四位相当于原数除以1000后结果的最后一位数, 7 * ...

  9. python基础练习题(题目 取一个整数a从右端开始的4〜7位。)

    day36 --------------------------------------------------------------- 实例054:位取反.位移动 题目 取一个整数a从右端开始的4 ...

随机推荐

  1. Java精通并发-锁升级与偏向锁深入解析

    对于synchronized关键字,我们在实际使用时可能经常听说用它是一个非常重的操作,其实这个“重”是要针对JDK的版本来说的,如今JDK已经到了12版本了,其实对这个关键字一直是存在偏见的,它底层 ...

  2. 【转】An introduction to using and visualizing channels in Go

    An introduction to using and visualizing channels in Go 原文:https://www.sohamkamani.com/blog/2017/08/ ...

  3. Maven安装及其IDEA的配置

    相关内容网上很多,本文转载自csdn博主 击中我,https://blog.csdn.net/qq_36267611/article/details/85274885,内文略有修改. 一.下载安装前往 ...

  4. 创建型模式(过渡模式) 简单工厂模式(Simple Factory)

    简单工厂模式(Simple Factory Pattern)属于类的创建型模式,又叫静态工厂方法模式(Static FactoryMethod Pattern) 是通过专门定义一个类来负责创建其他类的 ...

  5. PHP——json_encode转码保留中文

    前言 特殊的情况,特殊对待吧.转码为GBK再json_encode会报错,因为json_encode是只支持utf8的. 代码 文档 | https://www.php.net/manual/en/f ...

  6. pycharm 远程修改服务器代码

    首先在本地和服务器上下载pydevd pip3 install pydevd 然后在 设置SSH连接, 出现:java.net.ConnectException:Connection refused ...

  7. 多线程实现的方式二实现Rannable

    package thread; class Thread2 implements Runnable{ private String name; public Thread2(String name) ...

  8. 精妙的SQL语句

      说明:复制表(只复制结构,源表名:a 新表名:b)select * into b from a where 1<>1 说明:拷贝表(拷贝数据,源表名:a 目标表名:b)insert i ...

  9. learning java Calendar类

    //Calendar.MONTH ,这是一个特殊于日历的值. //在格里高利历和罗马儒略历中一年中的第一个月是 JANUARY,它为 0:最后一个月取决于一年中的月份数. // //所以这个值的初始值 ...

  10. 《挑战30天C++入门极限》C/C++中结构体(struct)知识点强化

        C/C++中结构体(struct)知识点强化 在上一个教程中我们已经简单的阐述了什么是结构体了,为了进一部的学习结构体这一重要的知识点,我们今天来学习一下链表结构. 结构体可以看做是一种自定义 ...