散列之HashTable学习
1,什么是散列?
举个例子,在日常生活中,你将日常用品都放在固定的位置,当你下次需要该东西时,直接去该地方取它。这个过程就相当于散列查找。
若将它们随意杂乱无章地存放,当需要某件东西时,只能一个地方一个地方地逐一查找,这就相当于顺序查找。
在数据结构中,数组就相当于一张散列表,因为可以根据数组下标索引直接取得该位置上的元素。
2,什么情况下用到散列?
由于散列查找相对于其它查找而言,理论上只需要O(1)时间就可以找到某元素,因此,当查找是主要的任务时,散列就是实现词典的一种很好的选择。
3,散列函数的理解
散列查找中,需要提供一个查找键,根据该查找键来寻找值---(KEY,VALUE)....而在实际应用中,查找键描述的是现实世界中对象的性质,它不合适直接用来作为Value(值)的索引(索引一般是整数)。其次,查找键的范围可能很大,但是计算机的存储是空间使用得越少越合理。基于以上两个原因,需要使用散列函数将查找键转化为某个元素的索引。对于一个典型的散列函数,执行以下两个步骤:
①将查找键转换为一个称为散列码的整数-------解决索引问题
②将散列码压缩到散列表的索引范围------解决存储空间限制
4,在Java中,JDK类库String类的对象的hashCode是这样生成的:
对于字符串s而言,它的hashCode是基于每个字符unicode值乘以一个基于该字符在字符串中位置的因子g(其中 g=31)
如: s = u(0)u(1)……u(n-1)
散列码hash = u(0)*g^(n-1) + u(1)*g^(n-2)+……+u(n-2)*g+u(n-1),该多项式使用 Horner方法 可以写成一种等价的代数形式。该代数形式的多项式求值用程序表示如下:
int hash = ;
int n = s.length();
for(int i = ; i < n; i++)
hash = g*hash + s.charAt(i);
5,JDK中对于64位long类型对象作为key的hashCode码按照如下方法生成:
int(key^(key>>32))
key一共有64位,首先将key右移32位(高32位补0),原来的key低32位的值被丢弃,再进行异或运算,就可以合并64位查找键的低32位的值和高32位的值(key中高32位的bit与低32位的bit异或),再运行强制类型转换,将结果转化成32位的值。这样就可以将一个64位的key结合它的每一位的值来获得一个32位的hashCode散列码。
6,散列表长度问题
散列表的长度不能为偶数,why?因为在将散列码压缩为散列表的索引时,通常是使用取模计算---c%n(c 为散列码,n 为散列表长度)
当 n 为偶数时,c%n 的奇偶性与 c 的奇偶性相同,若散列码偏向于奇数或者偶数(内存地址的散列码通常是偶数)这样得到的索引很难是均匀分布的。因此散列表的长度通常取奇数,最好取素数。
7,散列冲突的处理
这个知识点可以单独写一篇文章了。当在词典中插入元素时,若散列函数将查找键映射到一个已经使用的位置,则需要为该查找键相关联的值寻找另一个位置,有两种思路,一是使用散列表中的另一个位置。二是修改散列表的结构,使得散列表中的每个位置可以表示多个值。
这样列下散列冲突的处理类型分两种:
①开放定址法---对应第一种思路,总是为冲突的key在散列表中寻找下一个“未被使用”的位置。
②链地址法-----对应第二种思路,每个散列表中的位置可以指向一个链表,该链表称为桶。每个桶中则可以存放多个value。(将冲突的key对应的value插入到链表中)
开放定址法又分为三种情况:
❶线性探测开放定址----易产生一次聚集现象,即多个key问题被hash到同一个索引位置上。对于每个(key,value)只要表不满,总可以找到一个位置存放。
❷二次探测开放定址
❸再散列法---对冲突的key再进行一次hash。
散列之HashTable学习的更多相关文章
- 数据结构和算法 – 7.散列和 Hashtable 类
7.1.散列函数 散列是一种常见的存储数据的技术,按照这种方式可以非常迅速地插入和取回数据.散列所采用的数据结构被称为是散列表.尽管散列表提供了快速地插入.删除.以及取回数据的操作,但是诸如查找最大值 ...
- PHP密码散列算法的学习
不知道大家有没有看过 Laravel 的源码.在 Laravel 源码中,对于用户密码的加密,使用的是 password_hash() 这个函数.这个函数是属于 PHP 密码散列算法扩展中所包含的函数 ...
- 哈希表(散列)HashTable实现
近期刷Leetcode发现凡是找字符串中反复字符或者数组中找反复数据的时候就不知道从何下手了. 所以决定学习一下哈希表解题.哈希表的原理主要是解决分类问题,hash表是介于链表和二叉树之间的一种中间结 ...
- 流畅的python第十章序列的修改,散列和切片学习记录
只要实现了__len__和__getitem__两个方法即可将该类视为序列. 切片原理 动态存取属性 如果实现了__getattr__方法,也要定义__setattr__方法,以防对象行为不一致
- js 实现数据结构 -- 散列(HashTable)
原文: 在Javascript 中学习数据结构与算法. 概念: HashTable 类, 也叫 HashMap 类,是 Dictionary 类的一种散列表实现方式. 散列算法的作用是尽可能快地在数据 ...
- 基于散列的集合 HashSet\HashMap\HashTable
HashSet\HashMap\HashTable 1 基于散列的集合 2 元素会根据hashcode散列,因此,集合中元素的顺序不一定与插入的顺序一致. 3 根据equals方法与hashCode方 ...
- 散列表碰撞处理、开链法、HashTable散列
散列表碰撞处理.开链法.HashTable散列 /** * 散列表碰撞处理.开链法.HashTable散列. * 将数组里的元素位置,也设置为数组,当两个数据的散列在同一个位置时, * 就可以放在这个 ...
- Shiro入门学习之散列算法与凭证配置(六)
一.散列算法概述 散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法如MD5.SHA等,一般进行散列时最好提供一个salt(“盐”),什么意思?举个栗子 ...
- 【数据结构与算法Python版学习笔记】查找与排序——散列、散列函数、区块链
散列 Hasing 前言 如果数据项之间是按照大小排好序的话,就可以利用二分查找来降低算法复杂度. 现在我们进一步来构造一个新的数据结构, 能使得查找算法的复杂度降到O(1), 这种概念称为" ...
随机推荐
- scope 前缀开头的方法
https://learnku.com/docs/laravel/5.6/eloquent/1403 本地范围 本地范围允许定义通用的约束集合以便在应用中复用. 例如, 你可能经常需要获取「受欢迎的」 ...
- centos7切换gnome3桌面与gnome经典桌面
登陆界面选择设置按钮,选择gnome,进行登陆
- 在保存Bitmap的时候出现“GDI出现一般性错误”
今天开发的时候出现过一个非常奇怪的问题,在保存最终的Bitmap图片的时候,明明使用Directory.Exist(filePath)函数判断当前路径的时候,这些路径都是有用的并且都是合法的,但是就是 ...
- the project already contains a form or module named pcm001怎麼解決
the project already contains a form or module named pcm001怎麼解決 菜单Project -> Remove from project.. ...
- jquery stop()、callback、鏈接
stop(stopAll,goToEnd) stop適用於所有的效果,包括顯示隱藏.滑動.淡入淡出和動畫. stopAll默認值為false,清除當前動畫,可以向後執行下一動畫調用,黨改為true,清 ...
- 微信小程序的界面下拉刷新
小程序的下拉刷新的值设置:需要设置app.json的window中 "navigationBarTextStyle":true
- java 里面的 native 方法
第一篇: 今天花了两个小时把一份关于什么是Native Method的英文文章好好了读了一遍,以下是我依据原文的理解. 一. 什么是Native Method 简单地讲,一个Native Meth ...
- 我的Linux系统九阴真经
在今天,互联网的迅猛发展,科技技术也日新月异,各种编程技术也如雨后春笋一样,冒出尖来了.各种创业公司也百花齐放百家争鸣,特别是针对服务行业,新型互联网服务行业,共享经济等概念的公司,越来越多.有一些公 ...
- Enea推出Linux实时加速方案专门针对Xilinx UltraScale+
导读 Enea(纳斯达克OMX Nordic:ENEA)Linux实时加速方案的扩展版本,完全集成了Xilinx UltraScale +系列的所有处理单元.借助Xilinx开发者大会(XDF)201 ...
- hdu 4348 To the moon (主席树 区间更新)
链接: http://acm.hdu.edu.cn/showproblem.php?pid=4348 题意: 4种操作: C l r c 区间[l,r]加c,时间+1 Q l r 询问当前时 ...