本节内容:

  • 散列函数

  • 散列表的应用

  • 冲突

  • 性能

  • 小结

散列函数

散列函数的定义:将输入映射到数字

实现散列函数的要求:

  • 必须一致:即同样的值经过散列函数,返回的值必须是一样的『注意:就算不同的输入得到的是相同的值,只要是同样的数输入得到的同样的值就是一致,f(x)=1 是满足一致的!』

  • 应该将不同的输入映射到不同的数字。例如, 如果一个散列函数不管输入是什么都返回 1,它就不是好的散列函数。最理想的情况是,将不同的输入映射到不同的数字。

散列函数能够准确的指出输入对应的输出的位置:

  • 散列函数总是将同样的输入映射到相同的索引。

  • 散列函数将不同的输入映射到不同的索引。

  • 散列函数知道数组有多大,只返回有效的索引。

通过散列函数和数组实现散列表(hash table)

散列表可能是最有用的,也被称为散列映射、映射、字典和关联数组。散列表的速度很快!

散列表的应用

  • 散列表用于查找:手机薄,一个联系人对应一个手机号码

  • 防止重复:投票系统防止同一个用户进行重复投票

  • 用于缓存:网页的缓存机制(网站将数据记住,而不再重新计算。),如用户未登录时,显示相同的内容,用户登录时,向服务器请求新的网页。缓存的优点:用户能够更快地看到网页,降低服务器负载。『缓存是一种常用的加速方式,所有大型网站都使用缓存,而缓存的数据则存储在散列表中!』

1# 创建一个手机薄
2# 添加联系人及其电话号码。通过输入联系人来获悉其电话号码。
3phone_book = dict()
4phone_book["Bob"] = 123   # 添加新联系人
5phone_book["Logan"] = 567 # # 添加新联系人
6phone_book["Bob"] # 查询联系人

 1# 投票检测系统2# 首次投票让其进行投票,投过票以后将其加入已投票名单,若重复投票将被检测出来3voted = dict()4def check_voter(name):5    if voted.get(name):6        print("kick them out!")7    else:8        voted[name] = True9        print("let them vote!")
10
11check_voter("Bob") # let them vote!
12check_voter("Logan") # let them vote!
13check_voter("Bob") # kick them out!  因为已经投过票了

 1def get_data_from_server(url):2    # 模拟向服务器请求3    return url45cache = {}6def get_page(url):7    if cache.get(url):8        print("get info from local!")9        return cache[url]  # 返回缓存的数据
10    else:
11        data = get_data_from_server(url)
12        cache[url] = data  # 将数据保存于缓存中
13        print("get info from server!")
14        return data
15
16get_page("www.google.com")  # get info from server!
17get_page("www.bing.com")  # get info from server!
18get_page("www.google.com")  # get info from local!

冲突

创建散列函数是怎样引起冲突的呢?

如果创建的数据大小小于我们要存储的数据量,那么会导致每个数据不能对应唯一到数组上的位置。例如我们创建一个长度为 26 的数组(英文字母的个数),用它来存储所有的英文单词,明显他并不符合我们创建散列函数的要求。这就形成了冲突:冲突很糟糕,必须要避免。

解决的办法是:如果两个键映射到了同一个位置,就在这个位置存储一个链表。

但是此时又会引起一个问题,假设世界上全部的单词都是以 A 开头的,那么我们就白白浪费了 A 后面的其他位置。换言之,这个散列表中的所有元素都在这个链表中,这与一开始就将所有元素存储到一个链表中一样糟糕:散列表的速度会很慢。

故有两条经验法则:

  • 散列函数很重要。最理想的情况是,散列函数将键均匀地映射到散列表的不同位置。

  • 如果散列表存储的链表很长,散列表的速度将急剧下降。

性能

如何创建一个“好”的散列表,极其影响其性能。

在平均情况下,散列表的查找(获取给定索引处的值)速度与数组一样快,而插入和删除速度与链表一样快,因此它兼具两者的优点!但在最糟情况下,散列表的各种操作的速度都很慢。因此在使用散列表时,避开最糟情况至关重要。为此,需要避免冲突。避免冲突的几个指标是:

  • 较低的填装因子:填装因子 = 散列表包含的元素数/位置总数

  • 良好的散列函数:让数组中的值呈均匀分布。

小结

  • 大部分编程语言已经实现散列表,python 中的字典等,

  • 散列表是一种功能强大的数据结构,其操作速度快,还能让你以不同的方式建立数据模型

  • 你可以结合散列函数和数组来创建散列表。

  • 冲突很糟糕,应使用可以最大限度减少冲突的散列函数。

  • 散列表的查找、插入和删除速度都非常快。

  • 散列表适合用于模拟映射关系。

  • 一旦填装因子超过 0.7,就该调整散列表的长度。

  • 散列表可用于缓存数据(例如,在Web服务器上)。

  • 散列表非常适合用于防止重复。

参考资料: 图解算法





感谢您的关注与支持!

数据结构与算法-散列表相关推荐

  1. 数据结构与算法 / 散列表(HashTable)

    一.散列思想 通过散列函数通过 Key 值计算得出数组下标,然后利用数组支持下标随机访问的特性,在时间复杂度为O(1)的情况下找到所需要的信息. 散列函数Key -------------> 散 ...

  2. 数据结构与算法--散列表

    散列表 前言 一.什么是散列表 二.HashMap 三.散列表原理 四.散列函数的设计 五.解决散列冲突的方法 1.开放寻址法 2.链表法 总结 前言 散列表也叫哈希表,是根据键值对(key,valu ...

  3. 学习JavaScript数据结构与算法 — 散列表

    定义 散列表是字典(键.值对)的一种实现方式.每次在字典中获取一个值,都需要重复遍历字典,如果用散列表,字典中的每个key都对应一个确定的位置,从而不再需要遍历. 以电子邮件地址簿为例,每个名字(ke ...

  4. 数据结构与算法文章列表

    前言 数据结构与算法文章列表主要内容包括:稀疏数组.单向队列.环形队列.单向链表.双向链表.环形链表.约瑟夫问题.栈.前缀.中缀.后缀表达式.中缀表达式转换为后缀表达式.递归.迷宫问题.八皇后问题.散 ...

  5. 高速缓存的数据结构:拉链散列表

    高速缓存的底层数据结构:拉链散列表,很多bucket,挂了很多cache entry(tag + cache line + flag). cache line就是缓存的数据,包含多个变量的值 tag指 ...

  6. python中的列表是采用链式结构实现的_Python数据结构与算法之列表(链表,linked list)简单实现...

    Python数据结构与算法之列表(链表,linked list)简单实现 Python 中的 list 并不是我们传统(计算机科学)意义上的列表,这也是其 append 操作会比 insert 操作效 ...

  7. 【数据结构】回顾散列表

    1.散列表(hash table)的实现成为散列(hashing),是一种以常数平均时间执行输入.删除和查找的技术.但是那些需要元素间任何排序信息的数操作将不会得到有效的支持. 2.散列函数示例 in ...

  8. 数据结构--hashtable(散列表)

    散列 散列又叫hash.是通过关键字把数据映射到指定位置的一种数据结构.理想的散列表,是一个包含关键字的固定大小的数组 哈希表存储的是键值对,其查找的时间复杂度与元素数量多少无关,哈希表在查找元素时是 ...

  9. 用js来实现那些数据结构12(散列表)

    上一篇写了如何实现简单的Map结构,因为东西太少了不让上首页.好吧... 这一篇文章说一下散列表hashMap的实现.那么为什么要使用hashMap?hashMap又有什么优势呢?hashMap是如何 ...

  10. 《数据结构与算法》(二十)- 散列表查找

    目录 前言 1. 散列表查找(哈希表)概述 1.1 散列表查找定义 1.2 散列表查找步骤 2. 散列函数的构造方法 2.1 直接定址法 2.2 数字分析法 2.3 平方取中法 2.4 折叠法 2.5 ...

最新文章

  1. 视觉SLAM学习(三)--------SLAM 综述
  2. 七喜携手AMD,摆脱英特尔“潜规则”
  3. python如何返回多个值_python- 如何返回多个值 | 学步园
  4. 了解Android中的meta-data及其应用
  5. 关联查询取更新时间_数据分析之sql复杂查询
  6. hdu 1251 统计难题(trie树入门)
  7. c# 无损高质量压缩图片代码
  8. Jade/Pug模板引擎
  9. 计算机病毒是具有破坏性的程序6,2015年计算机二级MS Office习题及答案解析(6)
  10. 9.企业应用架构模式 --- 领域逻辑模式
  11. LINUX模拟键盘F5的脚本(未试过)
  12. 基于sklearn的线性分类器
  13. 关于主机名,域名区别(www.baidu.com与baidu.com)以及同源策略的一些误区
  14. win10 oracle11g 乱码,小编教你解决win10系统出现汉字乱码的处理办法
  15. 天原笔记(5) 天气形势及天气要素的预报
  16. IAR无法调试问题解决
  17. C语言自定义函数的调用
  18. 测试成绩软件,软件部分测试成绩_精英 Z87H3-A3X_主板评测-中关村在线
  19. 七夕送礼必备好物,品质好的蓝牙耳机分享
  20. Android 解压zip压缩包 (压缩包内有多级目录)

热门文章

  1. java jui_求教java大神,下面这个JUI界面是怎么布局而成的
  2. 射频可编程数字信号发生器的三大特点
  3. C/C++复习:向量的数量积
  4. C ++ 扑克牌洗牌
  5. 平板触控笔有哪些用途?实用平板电脑手写电容笔推荐
  6. 并行程序设计整理(一)
  7. 上网行为管理软件的功能
  8. c语言赋值运算符大全,C语言基础学习运算符-赋值运算符(示例代码)
  9. 人居一世间, 忽若风吹尘 2019.07.07.
  10. 【解决】updateAppMessageShareData:fail, the permission value is offline verifying