常见数据类型的散列函数
散列函数(又称哈希函数)就是在符号表中将被查找的键转化为一个数组的索引,便于键值对的查询
一、正整数的散列函数
如果所有的键都是小整数,那么可以直接将键作为数组的一个索引。
如(1,A)、(2,B)、(3,C)
除留余数法
选择大小为素数M的数组,对于任意正整数k,计算k除以M的余数,将余数作为索引值。
例如一个60人的班级的同学们的学号与姓名作为键值对
张小芳 | 2131469 |
王钢蛋 | 2131587 |
刘大皮 | 2131694 |
李好 | 2131447 |
..... | ...... |
前两位21表示 2021年入学,第三四位31表示专业,后三位469表示编号。
直接将学号作为数组索引需要创建一个百万长度的数组去存60个人的信息过于浪费,取后三位作为索引会减少很多空间。但是长度1000的数组储存60条信息似乎还是浪费,这时可以用除留余数法。
选择大小为素数 M = 61 的数组,将每位同学学号后三位除以61得到余数如下
张小芳 | 42 |
王钢蛋 | 38 |
刘大皮 | 23 |
李好 | 20 |
... | ... |
取数组大小为素数 M = 61 是为了更好的分布分散,假如取 M = 100,369、469与569的余数都是69,而无法利用百位数字的信息,在选择散列函数时应尽可能地利用所有信息。当然取比60更大地素数会有更好地散列值分布,要平衡数组大小与散列值分布。
二、浮点数的散列函数
如果键是0-1之间的实数,可以将它乘以M并四舍五入得到一个(0, M-1)之间的一个整数作为索引值,但是这种情况下键的高位起的作用更大,最低位几乎没有影响。例如,M=997,两个键分别为0.10001、0.10002,通过上述方法,得到的结果都是100。最低位的1和2(加粗部分)对结果没有影响。
将浮点数的键表示为二进制数然后使用除留余数法便可消除这种影响。计算机中保存浮点数的标准是IEEE 754\854标准。IEEE 754标准详解。
以32位单精度浮点数举例
如计算-9.875的散列值
首先转换为二进制形式,-1001.111,科学计数法为-1.001111✖2³。
S(符号位):该值为负所以符号位S为1;
E(指数位):指数是3,单精度偏置值是127,所以指数位为130(转换为二进制是10000010);什么是偏置值?因为指数位有可能为负,而指数位E无法表达负数,所以设置一个偏置值(,单精度为127,双精度就为1023)加上指数便是完整的指数位。如 1.01✖
,指数为-8,仅靠二进制无法表达,但是有偏置值,使-8加上偏置值127等于119,119容易二进制表示1110111。偏置值相当于指数位有个初始化的值,避免其变为负数。
M(有效数字位):有效数字位指的是小数点后面的数字001111,由于其是32位单精度浮点数,所以我们要保证S+E+M有32位。S+E已经有了8位,所以M有24位,我们将有效数字001111后面加0补齐其余位数得到00111100000000000000000。最终得到一个32位的二进制整数(下图所示)11000001000111100000000000000000,转换为十进制3239968768。
3239968768即为-9.875的散列值,然后可以用除留余数法。
三、字符串的散列函数
在Java中使用UTF-16编码,UTF-16编码方式是Unicode编码方式之一(字符编码方式)。因为在UTF-16编码方式中,其基本平面占用2个字节,辅助平面占用4个字节,常见字符都是由2个字节组成,所以一个字符可以转化为一个16位整数,从而逐个提取字符将字符串转化为一个特有的数值。
Java中自带的函数如下
public static int javahash(String str) {int hash = 0;for (int i = 0; i < str.length(); i++) {hash = hash * 31 + (int)str.charAt(i);}return hash & 0x7FFFFFFF;}
四、组合键
如果键的类型含有多个整形变量,可以和String类型一样将它们混合起来。
如Date数据类型,包括day,month,year。可以用如下方式计算散列值
int hash = (((day*R+month)%M)*R+year) % M;
五、将hashCode()的值转化为一个数组索引
因为需要的是数组的索引而不是一个32位整数,现实中会将默认的hashCode()方法和除留余数法结合起来产生一个0到M-1的整数:
private int hash(Key x)
{return (x.hashCode() & 0x7fffffff) % M;//M是素数
}
六、自定义hashCode
理想的hashCode方法是能够将键平均的分散到所有可能的32位整数,也就是说对于一个任意的对象x,x.hashCode() 可以有均等的机会获得
个不同整数任意一个数。Java中Integer、Double、String、URL、File对象的hashCode均能做到这一点。
例如定义一个数据类型Student
public class Student
{...private String name;private int number;private double gpa;...public int hashCode(){int hash = 17;hash = hash*31 + name.hashCode();hash = hash*31 + ((Integer)number).hashCode();//Java只有内置Integer类型的hashCode函 //数,因此int类型需要转化为包裹类型hash = hash*31 + ((Double)gpa).hashCode();return hash;}...
}
总结
散列函数的设置是个贼拉专业的技术,我不会。。
常见数据类型的散列函数相关推荐
- Redis常见数据类型_Redis通用指令
Redis常见数据类型 redis本身就是一个Map结构, 所有数据都采用key:value的形式, redis中的数据类型指的是value的类型, key部分永远是字符串 string(类似Java ...
- php易错,PHP学习1:几种常见数据类型及其易错点
PHP学习1:几种常见数据类型及其易错点 (本篇随笔就是关于几种常见数据类型及其易错点,适合初学者观看,并未包含全部九种数据类型,且通篇以代码和注释的形式来呈现.) /* 双引号字符串和单引号字符串之 ...
- c语言中最常用的四种数据类型,计算机中有哪几种常见数据类型
计算机中有哪几种常见数据类型 数据类型在数据结构中的定义是一个值的集合以及定义在这个值集上的一组操作.下面是YJBYS小编带来的计算机中有哪几种常见数据类型介绍,希望对你有帮助. 一.指令系统概述 指 ...
- date类型_Chapter 01. 常见数据类型概述 Overview of Common Data Types
课程:DataCamp_Skill Track_SQL fundamentals[笔记] Chapter 01. 常见数据类型概述 Overview of Common Data Types 了解常见 ...
- 深度解析javaScript常见数据类型检查校验
前言 在JavaScript中,数据类型分为两大类,一种是基础数据类型,另一种则是复杂数据类型,又叫引用数据类型 基础数据类型:数字Number 字符串String 布尔Boolean Null Un ...
- MySQL常见数据类型(小胖虎带你了解MySQL基础知识,只为博君一关注)
MySQL 常见数据类型 类型分类 类型 取值范围或描述 示例 整数类型 tinyint 0 -255 (长度最短) 员工年龄:32 smallint -32768-32767 员工数:2540 in ...
- C语言不同数据类型间的混合运算转换规则+常见数据类型
在程序中经常会遇到不同类型的数据进行运算,若一个运算符两侧的数据类型不同,则先自动进行类型转换,使两者具有同一类型,然后进行运算,现将规律总结如下: 1. +. -. *. /运算的两个数中有一个数为 ...
- MySQL的基本操作指令及常见数据类型
数据库 概念 数据库是"按照数据结构来组织.存储和管理数据的仓库".是一个长期存储在计算机内的.有组织的.可共享的.统一管理的大量数据的集合. 数据库是以一定方式储存在一起.能与多 ...
- Java常见数据类型举例及总结
一.Java常见数据类型举例 1.整型 运行结果如下: 2.长整型 运行结果如下: 3.短整型 运行结果如下: 4.双精度型 运行结果如下: 注: 在电脑中,小数没有一个最精确的值,它只能精确到小数点 ...
最新文章
- git fetch比较差异
- 洛谷 P1183 多边形的面积
- A Hierarchical Deep Temporal Model for Group Activity Recognition
- SQL Azure (15) SQL Azure 新的规格
- KVM虚拟化技术浅析
- 抱歉登录伺服务器暂时离线,为什么我离线了,换服务器的时候老提示我重复 – 手机爱问...
- java使用qq群发邮件_java群发发送qq邮件
- 二期开发立项申请书,已经提交,等待批准!
- 软件测试人员所不知道的软件测试七项原则
- 计算机英语pork,[语音]各种肉的英文
- 【Proteus仿真】Arduino UNO利用Stepper库实现uln2003驱动步进电机转动
- Ubuntu 20.04.2.0 LTS 更改默认关联视频播放器VLC的方法
- python中opencv 与 PIL读图区别,以及与Numpy转换
- 小米2s刷原生安卓_小米2S升级安卓5.0原生ROM下载刷机教程
- 网络中国象棋对战中象棋的规则以及棋盘、棋子的Java源码
- 先进工艺22nm FDSOI和FinFET简介
- 那些有趣的网站(二)
- 10进制、16进制(十进制、十六进制)与ASCII码流互转
- IndentationError:expected an indented block错误解决
- 网络流量异常检测综述