[MIT6.006] 8. Hashing with Chaining 散列表
一、字典
在之前课里,如果我们要实现插入,删除和查找,使用树结构,最好的时间复杂度是AVL下的Ο(log2n),使用线性结构,最好的复杂度为基数排序Ο(n)。但如果使用字典数据类型去做,时间复杂度可为Ο(1)。下面是对字典和Python中字典的相关内容:
字典本质上就是一个直接可接入的表,每个键内可存放一个数列的items。但因此也有坏处:
- 键不一定为非负整数;
- 消耗大量内存空间。
为了解决这两个问题,散列表被提出来了。
二、散列表
首先我们看下散列表是怎么解决字典第一个问题:键不一定为非负整数。
散列表使用prehash的方法将键变为非负整数,在Python里,hash(x)就是prehash,但需要注意的是有时候,x ≠ y,也有可能会有hash(x) = hash(y)。
关于字典第二问题:消耗大量内存空间,散列表通过hashing方法解决:
hashing方法可以将全部u个keys,减少为可接受的数量大小m。简单来说就是形成一个散列表,通过散列函数hash(x),将原来键空间内的键放入散列表中进行存放。因为散列函数本身会有冲突collision(即x ≠ y,但hash(x) = hash(y) ),所以散列表下某个键里可能有多个来自键空间内的items。而为了处理这种情况,拉链法Chaining出现了,它是将散列表每个槽内中的冲突元素进行链接,可视化如下:
如果该散列表是简单平均式散列(即每个键被平均(uniformally)地hash到表内的槽里,并且各键hashing是独立的(independently)),并假设有n个keys和m个槽,那么散列表里链长度为n / m = α = load factor。而运行时间为Ο(1 + |chain|) = Ο(1 + α), 其中1指计算hash的时间,|chain|是指形成chain的时间等于它的长度。
三、散列函数
该课只讲了三种散列函数:Divison Method,Multiplication Method和Universal Hashing。最后一种比前两种能更好地避免冲突。
(1)Divison Method
h(k) = k mod m (mod为求余)
(2)Multiplication Method
h(k) = [(a * k) mod 2w] >> (w - r) (k为w bits,m=2r, ‘>>’为shift right操作)
最后结果为阴影部分。
(3)Universal Hashing
h(k) = [(a * k + b) mod p] mod m (a和b为从{0,...,p-1}中抽取的随机数,p为大于|u|的质数,质数是只能被1和自身整除的数,u为key space的大小)
对于最差情况k1 ≠ k2下, P{h(k1) = h(k2)} = 1 / m,其小于简单平均式散列下的n / m。
[MIT6.006] 8. Hashing with Chaining 散列表的更多相关文章
- [MIT6.006] 9.  Table Doubling, Karp-Rabin 双散列表, Karp-Rabin
		在整理课程笔记前,先普及下课上没细讲的东西,就是下图,如果有个操作g(x),它最糟糕的时间复杂度为Ο(c2 * n),它最好时间复杂度是Ω(c1 * n),那么θ则为Θ(n).简单来说:如果O和Ω可以 ... 
- [MIT6.006] 10. Open Addressing, Cryptographic Hashing 开放定址,加密哈希
		前几节课讲散列表的时候,我们需要用Chaining,链接法需要用到指针pointer,但有一种方法可以不要Chaining和指针,还能在发生冲突时,为产生冲突的关键字寻找下一个"空" ... 
- PAT-1078 Hashing (散列表 二次探测法)
		1078. Hashing The task of this problem is simple: insert a sequence of distinct positive integers in ... 
- 散列表 (Hash table,也叫哈希表)
		散列表是根据关键字(Key value)而直接访问在内存存储位置的数据结构.也就是说,它通过把键值通过一个函数的计算,映射到表中一个位置来访问记录,这加快了查找速度.这个映射函数称做散列函数,存放记录 ... 
- Python数据结构——散列表
		散列表的实现常常叫做散列(hashing).散列仅支持INSERT,SEARCH和DELETE操作,都是在常数平均时间执行的.需要元素间任何排序信息的操作将不会得到有效的支持. 散列表是普通数组概念的 ... 
- Java数据结构与算法解析(十二)——散列表
		散列表概述 散列表就是一种以 键-值(key-indexed) 存储数据的结构,我们只要输入待查找的值即key,即可查找到其对应的值. 散列表的思路很简单,如果所有的键都是整数,那么就可以使用一个简单 ... 
- 散列表(hash table)——算法导论(13)
		1. 引言 许多应用都需要动态集合结构,它至少需要支持Insert,search和delete字典操作.散列表(hash table)是实现字典操作的一种有效的数据结构. 2. 直接寻址表 在介绍散列 ... 
- [转载] 散列表(Hash Table)从理论到实用(上)
		转载自:白话算法(6) 散列表(Hash Table)从理论到实用(上) 处理实际问题的一般数学方法是,首先提炼出问题的本质元素,然后把它看作一个比现实无限宽广的可能性系统,这个系统中的实质关系可以通 ... 
- [转载] 散列表(Hash Table)从理论到实用(中)
		转载自:白话算法(6) 散列表(Hash Table)从理论到实用(中) 不用链接法,还有别的方法能处理碰撞吗?扪心自问,我不敢问这个问题.链接法如此的自然.直接,以至于我不敢相信还有别的(甚至是更好 ... 
随机推荐
- 风车签名 - 让管理APP变成一件简单的事儿
			这是一款在Mac平台下安全可控的iOS签名管理软件,旨在对签名后的APP能够完全控制,包括APP的开启或禁用.设置到期时间锁.注入第三方动态库文件.设置安装限量.修改APP名称和自定义Bundle I ... 
- 爬虫之Selenium
			简介 selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题 selenium本质是通过驱动浏览器,完全模拟浏览器的操作,比如 ... 
- Docker Stack 笔记
			Docker Compose (Docker Stack) image: Specify the image to start the container from. Can either be a ... 
- centos8上使用gitosis管理git项目
			零,centos8平台如何安装gitosis服务? 参见:centos8平台安装gitosis服务 地址:https://www.cnblogs.com/architectforest/p/12456 ... 
- PHP SPL标准库-迭代器
			通过某种统一的方式遍历链表或者数组中的元素的过程叫做迭代遍历,这种统一的遍历工具我们叫做迭代器. PHP中迭代器是通过Iterator 接口定义的. ArrayIterator迭代器 foreach ... 
- 浏览器页面左上角出现undefined
			浏览器页面左上角出现undefined, js文档中: let list; list += html代码; 解决办法: let list = html代码; 
- Java进阶--Java动态代理
			JDK version: 1.8 动态代理中所说的"动态", 是针对使用Java代码实际编写了代理类的"静态"代理而言的, 它的优势不在于省去了编写代理类那一点 ... 
- C#Socket通讯(1)
			前言 因为自己需要开发一款自己的游戏,因为设计网络方面,所以我找了很多的资料,再加上考虑到Unity游戏客户端直接连接数据库很容易导致数据库泄露,再加上网上很多的服务端都是用控制台做的,所以我就想做个 ... 
- C#语言下使用gRPC、protobuf(Google Protocol Buffers)实现文件传输
			初识gRPC还是一位做JAVA的同事在项目中用到了它,为了C#的客户端程序和java的服务器程序进行通信和数据交换,当时还是对方编译成C#,我直接调用. 后来,自己下来做了C#版本gRPC编写,搜了很 ... 
- C#一行代码实现(01)最小化到通知区域
			主要功能 实现Winform程序最小化后,隐藏任务栏显示,在通知区域显示.左键点击通知区域图标,可以弹出菜单,包含开机启动和退出程序,可以根据需求进行定制. 一行代码 private void For ... 
