一、字典

在之前课里,如果我们要实现插入,删除和查找,使用树结构,最好的时间复杂度是AVL下的Ο(log2n),使用线性结构,最好的复杂度为基数排序Ο(n)。但如果使用字典数据类型去做,时间复杂度可为Ο(1)。下面是对字典和Python中字典的相关内容:

字典本质上就是一个直接可接入的表,每个键内可存放一个数列的items。但因此也有坏处:

  1. 键不一定为非负整数
  2. 消耗大量内存空间

为了解决这两个问题,散列表被提出来了。

二、散列表

首先我们看下散列表是怎么解决字典第一个问题:键不一定为非负整数。

散列表使用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 散列表的更多相关文章

  1. [MIT6.006] 9. Table Doubling, Karp-Rabin 双散列表, Karp-Rabin

    在整理课程笔记前,先普及下课上没细讲的东西,就是下图,如果有个操作g(x),它最糟糕的时间复杂度为Ο(c2 * n),它最好时间复杂度是Ω(c1 * n),那么θ则为Θ(n).简单来说:如果O和Ω可以 ...

  2. [MIT6.006] 10. Open Addressing, Cryptographic Hashing 开放定址,加密哈希

    前几节课讲散列表的时候,我们需要用Chaining,链接法需要用到指针pointer,但有一种方法可以不要Chaining和指针,还能在发生冲突时,为产生冲突的关键字寻找下一个"空" ...

  3. PAT-1078 Hashing (散列表 二次探测法)

    1078. Hashing The task of this problem is simple: insert a sequence of distinct positive integers in ...

  4. 散列表 (Hash table,也叫哈希表)

    散列表是根据关键字(Key value)而直接访问在内存存储位置的数据结构.也就是说,它通过把键值通过一个函数的计算,映射到表中一个位置来访问记录,这加快了查找速度.这个映射函数称做散列函数,存放记录 ...

  5. Python数据结构——散列表

    散列表的实现常常叫做散列(hashing).散列仅支持INSERT,SEARCH和DELETE操作,都是在常数平均时间执行的.需要元素间任何排序信息的操作将不会得到有效的支持. 散列表是普通数组概念的 ...

  6. Java数据结构与算法解析(十二)——散列表

    散列表概述 散列表就是一种以 键-值(key-indexed) 存储数据的结构,我们只要输入待查找的值即key,即可查找到其对应的值. 散列表的思路很简单,如果所有的键都是整数,那么就可以使用一个简单 ...

  7. 散列表(hash table)——算法导论(13)

    1. 引言 许多应用都需要动态集合结构,它至少需要支持Insert,search和delete字典操作.散列表(hash table)是实现字典操作的一种有效的数据结构. 2. 直接寻址表 在介绍散列 ...

  8. [转载] 散列表(Hash Table)从理论到实用(上)

    转载自:白话算法(6) 散列表(Hash Table)从理论到实用(上) 处理实际问题的一般数学方法是,首先提炼出问题的本质元素,然后把它看作一个比现实无限宽广的可能性系统,这个系统中的实质关系可以通 ...

  9. [转载] 散列表(Hash Table)从理论到实用(中)

    转载自:白话算法(6) 散列表(Hash Table)从理论到实用(中) 不用链接法,还有别的方法能处理碰撞吗?扪心自问,我不敢问这个问题.链接法如此的自然.直接,以至于我不敢相信还有别的(甚至是更好 ...

随机推荐

  1. 风车签名 - 让管理APP变成一件简单的事儿

    这是一款在Mac平台下安全可控的iOS签名管理软件,旨在对签名后的APP能够完全控制,包括APP的开启或禁用.设置到期时间锁.注入第三方动态库文件.设置安装限量.修改APP名称和自定义Bundle I ...

  2. 多测师讲解selenium_alert弹框定位_高级讲师肖sir

    from selenium import webdriverfrom time import sleepdrvier=webdriver.Chrome()url=r'F:\dcs\DCS课程安排\se ...

  3. 35岁的程序员正在消失?No,我认识了一个50岁的程序员!

    35岁的话题真是无穷无尽.一开始的时候,以为只有社交媒体上会有这种问题的讨论,没想到,公司内部的论坛上也有不少这类的文章.大家各有各的说法,但终究也没有找到银弹似的解决方案. 这段时间,倒是接触了一个 ...

  4. Spring源码解析之基础应用(二)

    方法注入 在spring容器中,大部分bean的作用域(scope)是单例(singleton)的,少部分bean的作用域是原型(prototype),如果一个bean的作用域是原型,我们A bean ...

  5. spring boot: 设计接口站api的版本号,支持次版本号(spring boot 2.3.2)

    一,为什么接口站的api要使用版本号? 1,当服务端接口的功能发生改进后, 客户端如果不更新版本,    则服务端返回的功能可能不能使用,    所以在服务端功能升级后,     客户端也要相应的使用 ...

  6. C# 8: 默认接口方法

    翻译自 John Demetriou 2018年8月4日 的文章 <C# 8: Default Interface Methods>[1],补充了一些内容 C# 8 之前 今天我们来聊一聊 ...

  7. 2020年的UWP(2)——In Process App Service

    最早的时候App Service被定义为一种后台服务,类似于极简版的Windows Service.App Service作为Background Task在宿主UWP APP中运行,向其他UWP A ...

  8. Vue基础语法(四)

    vue的生命周期钩子函数 所有的生命周期钩子自动绑定this到上下文实例中,因此可以访问数据对property和方法进行运算,这意味着不蹦使用箭头函数来定义一个生命周期方法.参考官方文档,生命周期图 ...

  9. Redis学习笔记(二)——Keys通用操作

    1.查询所有key: keys * 2.*通用符(代表0或多),查询所有以n(*)开头的key: keys n* 3.?通用符(代表1个字符): key n? 4.del删除key [key1 key ...

  10. C# stopwatch的简单使用(计算程序执行时间)

    首先添加引用 using System.Diagnostics;//stopwatch的引用 //声明变量 Stopwatch a=new Stopwatch();//PS:这里一定要new(实例化) ...