【算法图解】散列表

2023-11-03

一、引入

        如果我们需要查找一门课的学分(如《计算机算法设计与分析》(简称《算法》)这门课),如果教务做得很烂,所有课程都不是按照一定的顺序排列的,那么我们需要浏览每一行直到找到这门课,这将耗费我们O(n)的时间。而如果教务系统的学分排序是按照汉语拼音排序的,我们可以使用二分查找来找到《算法》这门课,这只需要耗费我们O(nlogn)的时间。

        而我们如果想要更快的速度,最好是查找一门课后马上就能得知这门课的学分,如果我们定义一个数组,这个数组的每个元素包含两项内容:课程名词和学分。如果将这个数组按课程名称顺序排序,我们就可使用二分查找在其中查找商品的价格。这样查找学分的时间将为O(logn)。          

        而我们想要获得学分的时间降为O(1),速度比二分查找都快,有没有可能呢? 


二、散列表的思路

        散列表可以实现这种要求,散列函数是这样的函数:即无论你给它什么数据,它都还你一个数字(即散列函数“将输入映射到数字"),但其实散列函数并不是随机输出数字,它必须满足一些要求:

        ①一致性。即输入《算法》这门课后得到的学分为3,那么下次输出还是3学分,下下次输出也是3学分,不会变成别的数字。如果不是这样,散列表将毫无用处。

        ②它应将不同的输入映射到不同的数字。如果一个散列函数不管输入师门都返回3,那么它就不是一个好的散列函数。最理想的情况是,将不同的输入映射到不同的数字。

        那么,现在来创建我们的散列表。例如,我们的《算法》课有3个学分,《数电》课有2个学分,《创业实践》课有1个学分。我们先创建一个空数组,数组的下标分别为0、1、2、3,我们将课程名称根据学分填写进去。

创业实践 数电 算法

        现在,我们需要查找《数电》课的学分。这时,我们不再需要查找数组,而是直接将《数电》作为输入告诉散列函数,它将告诉你《数电》课的学分,并输出学分2。

        散列函数准确地指出了学分的存储位置,大大降低了人力开销。而它之所以能够这样,具体原因如下:

        ①散列函数总是将同样的输入映射到相同的索引。每次输入《数电》得到的都是同一个数字。因此,我们可以首先定义《数电》存放于数组的位置,之后再从这个位置取出《数电》对应的值。

        ②散列函数将不同的输入映射到不同的索引。它将《数电》映射到索引2,将《算法》映射到索引3。每门课程都映射到数组的不同位置,让你能够将其学分存储到这里。

        ③散列函数知道数组有多大,只返回有效的索引。如果数组包含5个元素,散列函数就不会 返回无效索引100。

        而且,我们根本不需要自己去实现散列表!Python提供的 散列表实现为字典,你可使用函数dict创建散列表

        

xuefen = dict() 

        创建散列表xuefen后,在其中添加一些课程的学分。

>>> xuefen["Algorithm"] = 3
>>> xufen["digital circuit"] = 2
>>> xuefen["Entrepreneurship"] = 1
>>> print xuefen
{'Algorithm': 3, 'digital circuit': 2, 'Entrepreneurship': 1} 
#输入课程
print xuefen["digital circuit"]
#输出结果
2

        散列表由键和值组成。在前面的散列表xuefen中,键为课程名称,值为学分。散列表将键映射到值


三、散列表的应用其一

        我们的手机都内置了方便的电话簿,其中每个姓名都有对应的电话号码。假设你要创建一个类似这样的电话簿,将姓名映射到电话号码。该电话簿需要兼顾以下功能:

        ①添加联系人及其电话号码。

        ②通过输入联系人来获悉其电话号码。

        这非常适合使用散列表来实现。在需要满足创建映射、查找时,使用散列表是很不错的选择。

#创建电话簿非常容易。首先,新建一个散列表。
>>> phone_book = dict() 
#Python提供了一种创建散列表的快捷方式——使用一对大括号。
>>> phone_book = {} 
#这与phone_book = dict()等效
#下面在这个电话簿中添加一些联系人的电话号码。
>>> phone_book["jenny"] = 8675309 
>>> phone_book["emergency"] = 911 
#现在,假设你要查找Jenny的电话号码,为此只需向散列表传入相应的键。
>>> print phone_book["jenny"] 
#输出结果
8675309

四、散列表的应用其二

        假设你负责管理一个投票统计。显然,每人只能投一票,但如何避免重复投票呢?有人来投票时,你询问他的全名,并将其与已投票者名单进行比对。如果名字在名单中,就说明这个人投过票了,因此将他拒之门外。否则,就将他的姓名加入到已投票的人员名单中,并让他投票。现在假设有很多人来投过了票,因此名单非常长。

        每次有人来投票时,你都得浏览这个长长的名单,以确定他是否投过票。可以预见,这种方法非常耗费时间。但有一种更好的办法,那就是使用散列表

        为此,首先创建一个散列表,用于记录已投票的人

>>> voted = {} 

        有人来投票时,检查他是否在散列表中

>>> value = voted.get("tom") 
#如果“tom”在散列表中,函数get将返回它;否则返回None。你可使用这个函数检查来投票的人是否投过票
def check_voter(name): 
     if voted.get(name): 
        print "kick them out!" 
     else: 
        voted[name] = True 
        print "let them vote!" 

五、散列表的应用其三

        我们可以将散列表用作缓存。假设你访问网站csdn.net,需要经历以下的步骤:

        ①你向csdn的服务器发出请求。

        ②服务器做些处理,生成一个网页并将其发送给你。

        ③你获得一个网页。

        但csdn的服务器必须为数以百万的用户提供服务,为服务好所有用户,服务器如果每次都重新读取数据而不进行缓存的话累加起来将耗费大量的计算成本。有没有办法让csdn的服务器少做些工作,从而提高网站的访问速度呢?这里可以使用缓存

        缓存的使用有以下的优点:

        ①用户能够更快地看到网页

        ②网站需要做的工作更少

cache = {} 
    def get_page(url): 
        if cache.get(url): 
            return cache[url]    #返回缓存的数据
        else: 
            data = get_data_from_server(url) 
            cache[url] = data    #先将数据保存到缓存中
            return data 

        仅当URL不在缓存中时,你才让服务器做些处理,并将处理生成的数据存储到缓存中,再返 回它。这样,当下次有人请求该URL时,你就可以直接发送缓存中的数据,而不用再让服务器进行处理了

未完待续......

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【算法图解】散列表 的相关文章

随机推荐

  • MySQL【DQL查询数据(最重点)】

    DQL查询数据 最重点 4 1 DQL Data Query LANGUAGE 数据查询语言 所有的查询操作都用它 Select 简单的查询 复杂的查询它都能做 数据库中最核心的语言 最重要的语句 使用频率最高的语句 4 2 指定查询字段
  • HTML、CSS、JavaScript:网页开发的三大利器

    JavaScript 让网页更加生动有趣 JavaScript是一种广泛应用于网页开发的编程语言 它可以让网页更加生动有趣 在本文中 我们将介绍JavaScript的基本概念和应用 帮助读者更好地了解这个强大的编程语言 JavaScript
  • 一文读懂高速互联的阻抗及反射(中)

    一文读懂高速互联的阻抗及反射 中 勘误 上篇中 电感的电抗叫做感抗 表示为 X L j C
  • 2017网易游戏测试工程师-实习招聘在线笔试题

    网易游戏测试工程师 一 A游戏又要开新服了 为了在短时间内冲排名 你得尽可能多地完成游戏任务 通过事先查攻略我们知道了所有的游戏任务 以及每个任务的时间窗口 一旦选定了做某个任务 在所选定任务的整个持续时间内只能做这个任务 且只能等到当前任
  • SpringBoot整合多数据源Redis

    SpringBoot整合Redis 其实方法跟单数据差不多的 这里给大家写一下 文章目录 SpringBoot整合Redis 多数据源整合 多数据源整合 一 完成配置文件 Spring配置 spring 资源信息 messages 国际化资
  • python atexit模块的使用

    python atexit模块的使用 模块的简介 atexit模块主要的作用就是在程序即将结束之前执行的代码 atexit模块使用register函数用于注册程序退出时的回调函数 然后在回调函数中做一些资源清理的操作 该模块其实是一个对 s
  • 寻找峰值

    LeetCode 寻找峰值 峰值元素是指其值大于左右相邻值的元素 给定一个输入数组 nums 其中 nums i nums i 1 找到峰值元素并返回其索引 数组可能包含多个峰值 在这种情况下 返回任何一个峰值所在位置即可 你可以假设 nu
  • Eclipse、AndroidStudio

    Eclipse ADT SDK AndroidStudio Android Plugin for Gradle gradle SDK
  • 【自然语言处理】最大熵马尔可夫模型

    有任何的书写错误 排版错误 概念错误等 希望大家包含指正 由于这部分的参考资料比较少 网上大部分资料重复且不完整 对于一些关键计算没有推导 所以这里我主要讨论几篇论文和讲义 但是这些论文和讲义之间也有些许差别 讨论的过程中我会加入自己的理解
  • 百度网盘下载提速,推荐3种亲测有效的方法

    凉透的下载工具 自从PanDownload事件之后 陆续出了很多第三方的度盘不限速下载神器 但是最后都凉了 这些第三方下载神器 都是个人开发者 即便有盈利也承受不起巨大的风险 甚至有款下载神器 用爱发电 流程是这样的 1 用户提交下载链接
  • 34门课改变人生——牛人自学计算机总结

    转载说明 在人人网上看到一个在美国学生物的硕士通过MOOC学习最终找到IT工程师工作的故事 非常励志 而且每门课都有很有价值的点评 经过作者本人同意转载到MOOC学院 如果各位有后续问题可以把他本人拉来答疑 转载正文 首先这只是我个人的总结
  • Java小细节

    一 result null 和 result isEmpty 有什么区别 在 Java 中 result null 和 result isEmpty 是两个不同的检查 分别用于不同的目的 result null 这个检查用于确定变量 res
  • 最大平均值子数组

    最大平均值子数组
  • 企业级springboot项目架构模板V3.0,开箱即用

    此次 3 0 更新点 1 加入文件服务 quick storage 功能支持OSS FTP存储 该服务支持以SDK的方式引入 2 修复sentinel因path路径问题导致流控失效问题 3 修复word模板生成PDF文件工具类时首次生成时
  • 电子科技大学编译原理复习笔记(五):词法分析

    目录 前言 重点一览 词法分析概述 词法分析的功能 词法分析器的输出形式 词法分析器的结构 状态转换图 状态转换图的构造 词法分析器的设计 基本结构 内容 符号表 目的 组成 在词法分析中的作用 符号表的一般形式 常用的符号表结构 总结与补
  • 现有一个01串s,找出一个最长的连续子串。

    描述 如果一个01串任意两个相邻位置的字符都是不一样的我们就叫这个01串为交错01串 例如 1 10101 0101010 都是交错01串 现有一个01串s 找出一个最长的连续子串 并且这个字串是一个交错01串 求出最长的这样的子串的长度是
  • 华为CE6865交换机远程抓包

    一 背景 由于数据中心使用了VXLAN技术 导致在三层网络中查看不到原始的MAC数据帧 另外一个局限就是所有网络设备都不在本地 所以无法使用镜像技术进行抓包 最后决定使用交换机自带的抓包工具进行远程抓包 把抓包后的文件先保存在交换机上 然后
  • angularJS 报错: [ngModel:numfmt] http://errors.angularjs.org/1.4.1/ngModel/numfmt?p0=333

    pre stringToNumber2 指令中这么写没问题 但是html中调用也这么写 html解析会自动将标签和标签属性专为小写 即stringToNumber2变成了stringtonumber2 导致最终 Error ngModel
  • PandoraBox 端口映射设置

    http www right com cn forum forum php mod viewthread tid 161104
  • 【算法图解】散列表

    一 引入 如果我们需要查找一门课的学分 如 计算机算法设计与分析 简称 算法 这门课 如果教务做得很烂 所有课程都不是按照一定的顺序排列的 那么我们需要浏览每一行直到找到这门课 这将耗费我们O n 的时间 而如果教务系统的学分排序是按照汉语