数据结构
南方以北
这个作者很懒,什么都没留下…
展开
-
两个栈实现一个队列 两个队列实现一个栈
两个栈实现一个队列基础方法入队时,将元素压入s1。出队时,将s1的元素逐个“倒入”(弹出并压入)s2,将s2的顶元素弹出作为出队元素,之后再将s2剩下的元素逐个“倒回”s1。改进方法入队时,将元素压入s1。出队时,判断s2是否为空,如不为空,则直接弹出顶元素;如为空,则将s1的元素逐个“倒入”s2,把最后一个元素弹出并出队。这个思路,避免了反复“倒”栈,仅在...原创 2019-09-10 19:40:24 · 170 阅读 · 0 评论 -
【索引】:如何在海量数据中快速查找某个数据?
在【B+树】:MySQL数据库索引是如何实现的?中,我们讲了MySQL数据库索引的实现原理。MySQL底层依赖的是B+树这种数据结构。那类似Redis这样的Key-Value数据库中的索引,又是怎么实现的呢?底层依赖的有是什么数据结构呢?今天,我们来讲一下索引这种常用的技术解决思路,底层往往会依赖哪些数据结构。同时,通过索引这个应用场景,我也带你回顾一下,之前我们学过的几种支持动态集合的数据结...转载 2019-06-09 10:39:16 · 4212 阅读 · 0 评论 -
【动态规划实战】:如何实现搜索引擎中的拼写纠错功能?
在Trie 树那节我们讲过,利用 Trie 树,可以实现搜索引擎的关键词提示功能,这样可以节省用户输入搜索关键词的时间。实际上,搜索引擎在用户体验方面的优化还有很多,比如你可能经常会用的拼写纠错功能。当你在搜索框中,一不小心输错单词时,搜索引擎会非常智能地检测出你的拼写错误,并且用对应的正确单词来进行搜索。作为一名软件开发工程师,你是否想过,这个功能是怎么实现的呢?如何量化两个字符串的...转载 2019-05-29 11:15:04 · 1398 阅读 · 0 评论 -
【动态规划理论】:一篇文章带你彻底搞懂最优子结构、无后效性和重复子问题
上一节,我通过两个非常的问题,向你展示了用动态规划问题的过程。今天主要讲一些理论知识。学完这节内容,可以帮你解决这几个问题:什么样的问题可以用动态规划来解决?解决动态规划问题的一般思路是什么?贪心、分治、回溯、动态规划这四种算法思想又有什么区别和联系。“一个模型三个特征”理论的讲解动态规划作为一个非常成熟的算法思想,很多人对此做了非常全面的总结,我把这部分理论总结为“一个模型三个特征”。...转载 2019-05-28 11:25:28 · 25536 阅读 · 8 评论 -
【分治算法】:谈一谈大规模计算框架MapReduce中的分治思想
MapReduce 是 Google 大数据处理的三驾马车之一,另外两个是 GFS 和 Bigtable。它在倒排索引、PageRank 计算、网页分析等搜索引擎相关的技术中都有大量的应用。尽管开发一个 MapReduce 看起来很高深,感觉跟我们遥不可及。实际上,万变不离其宗,它的本质就是我们今天要学的这种算法思想,分治算法。如何理解分治算法?为什么说 MapRedue 的本质就是分...转载 2019-05-24 17:01:32 · 896 阅读 · 0 评论 -
【AC自动机】:如何用多模式串匹配实现敏感词过滤功能?
很多支持用户发表文本内容的网站,比如 BBS,大都会有敏感词过滤功能,用来过滤掉用户输入的一些淫秽、反动、谩骂等内容。你有没有想过,这个功能是怎么实现的呢?实际上,这些功能最基本的原理就是字符串匹配算法,也就是通过维护一个敏感词的字典,当用户输入一段文字内容之后,通过字符串匹配算法,来查找用户输入的这段文字,是否包含敏感词。如果有,就用“***”把它替代掉。我们前面讲过好几种字符串匹配算法...转载 2019-05-19 10:42:16 · 453 阅读 · 0 评论 -
【拓扑排序】:如何确定代码源文件的编译依赖关系?
从今天开始,我们就进入了专栏的高级篇。相对基础篇,高级篇涉及的知识点,都比较零散,不是太系统。所以,我会围绕一个实际软件开发的问题,在阐述具体解决方法的过程中,将涉及的知识点给你详细讲解出来。所以,相较于基础篇“开篇问题 - 知识讲解 - 回答开篇 - 总结 - 课后思考”这样的文章结构,高级篇我稍作了些改变,大致分为这样几个部分:“问题阐述 - 算法解析 - 总结引申 - 课后思考”。好...转载 2019-05-30 10:48:10 · 1795 阅读 · 1 评论 -
【40 | 初识动态规划】:如何巧妙解决“双十一”购物时的凑单问题?
淘宝的“双十一”购物节有各种促销活动,比如“满 200 元减 50 元”。假设你女朋友的购物车中有 n 个(n>100)想买的商品,她希望从里面选几个,在凑够满减条件的前提下,让选出来的商品价格总和最大程度地接近满减条件(200 元),这样就可以极大限度地“薅羊毛”。作为程序员的你,能不能编个代码来帮她搞定呢?要想高效地解决这个问题,就要用到我们今天讲的动态规划(Dynamic Prog...转载 2019-05-27 11:13:10 · 1717 阅读 · 0 评论 -
【回溯算法】:从电影《蝴蝶效应》中学习回溯算法的核心思想
我们在第 31 节提到,深度优先搜索算法利用的是回溯算法思想。这个算法思想非常简单,但是应用却非常广泛。它除了用来指导像深度优先搜索这种经典的算法设计之外,还可以用在很多实际的软件开发场景中,比如正则表达式匹配、编译原理中的语法分析等。除此之外,很多经典的数学问题都可以用回溯算法解决,比如数独、八皇后、0-1 背包、图的着色、旅行商问题、全排列等等。既然应用如此广泛,我们今天就来学习一下这个算...转载 2019-05-25 18:35:22 · 983 阅读 · 0 评论 -
【贪心算法】:如何用贪心算法实现Huffman压缩编码?
基础的数据结构和算法我们基本上学完了,接下来几节,我会讲几种更加基本的算法。它们分别是贪心算法、分治算法、回溯算法、动态规划。更加确切地说,它们应该是算法思想,并不是具体的算法,常用来指导我们设计具体的算法和编码等。贪心、分治、回溯、动态规划这 4 个算法思想,原理解释起来都很简单,但是要真正掌握且灵活应用,并不是件容易的事情。所以,接下来的这 4 个算法思想的讲解,我依旧不会长篇大论地去讲理...转载 2019-05-21 21:18:37 · 958 阅读 · 1 评论 -
【Trie树(字典树)】:如何实现搜索引擎的搜索关键词提示功能?
搜索引擎的搜索关键词提示功能,我想你应该不陌生吧?为了方便快速输入,当你在搜索引擎的搜索框中,输入要搜索的文字的某一部分的时候,搜索引擎就会自动弹出下拉框,里面是各种关键词提示。你可以直接从下拉框中选择你要搜索的东西,而不用把所有内容都输入进去,一定程度上节省了我们的搜索时间。尽管这个功能我们几乎天天在用,作为一名工程师,你是否思考过,它是怎么实现的呢?它底层使用的是哪种数据结构和算法呢?...转载 2019-05-17 11:46:33 · 1950 阅读 · 0 评论 -
【字符串匹配基础(下)】:如何借助BM算法轻松理解KMP算法?
上一节我们讲了 BM 算法,尽管它很复杂,也不好理解,但却是工程中非常常用的一种高效字符串匹配算法。有统计说,它是最高效、最常用的字符串匹配算法。不过,在所有的字符串匹配算法里,要说最知名的一种的话,那就非 KMP 算法莫属。很多时候,提到字符串匹配,我们首先想到的就是 KMP 算法。尽管在实际的开发中,我们几乎不大可能自己亲手实现一个 KMP 算法。但是,学习这个算法的思想,作为让你开拓眼界...转载 2019-05-16 09:09:06 · 198 阅读 · 0 评论 -
【字符串匹配基础(上)】:如何借助哈希算法实现高效字符串匹配?
从今天开始,我们来学习字符串匹配算法。字符串匹配这样一个功能,我想对于任何一个开发工程师来说,应该都不会陌生。我们用的最多的就是编程语言提供的字符串查找函数,比如 Java中的 indexOf(),Python 中的 find() 函数等,它们底层就是依赖接下来要讲的字符串匹配算法。字符串匹配算法很多,我会分四节来讲解。今天我会讲两种比较简单的、好理解的,它们分别是:BF 算法和 RK 算法。...转载 2019-05-07 19:21:23 · 266 阅读 · 0 评论 -
【最短路径】:地图软件是如何计算出最优出行路径的?
基础篇的时候,我们学习了图的两种搜索算法,深度优先搜索和广度优先搜索。这两种算法主要是针对无权图的搜索算法。针对有权图,也就是图中的每条边都有一个权重,我们该如何计算两点之间的最短路径(经过的边的权重和最小)呢?今天,我就从地图软件的路线规划问题讲起,带你看看常用的最短路径算法(Shortest Path Algorithm)。像 Google 地图、百度地图、高德地图这样的地图软件,我想你应...转载 2019-06-02 10:33:55 · 8215 阅读 · 1 评论 -
【位图】:如何实现网页爬虫中的URL去重功能?
转载地址:https://time.geekbang.org/column/article/76827网页爬虫是搜索引擎中的非常重要的系统,负责爬取几十亿、上百亿的网页。爬虫的工作原理是,通过解析已经爬取页面中的网页链接,然后再爬取这些链接对应的网页。而同一个网页链接有可能被包含在多个页面中,这就会导致爬虫在爬取的过程中,重复爬取相同的网页。如果你是一名负责爬虫的工程师,你会如何避免这些重复的...转载 2019-06-02 11:24:45 · 804 阅读 · 0 评论 -
Huffman树(哈夫曼树)
哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的带权路径长度记为WPL=(W1*L1+W2*L2+W3*L3+...+Wn*Ln),N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n)。可以...原创 2019-08-17 21:01:57 · 13951 阅读 · 0 评论 -
全排列和全组合实现
全排列所谓全排列,就是打印出字符串中所有字符的所有排列。例如输入字符串abc,则打印出 a、b、c 所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。一般最先想到的方法是暴力循环法,即对于每一位,遍历集合中可能的元素,如果在这一位之前出现过了该元素,跳过该元素。例如对于abc,第一位可以是 a 或 b 或 c 。当第一位为 a 时,第二位再遍历集合,发现...原创 2019-08-21 11:24:42 · 3832 阅读 · 0 评论 -
全排列
一.全排列算法首先:什么是全排列=》百度一下从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。公式:全排列数f(n)=n!(定义0!=1)算法:递归算法=》网络上偷了一个图全排列:顺便复习一个数学公式排列的定义:...转载 2019-08-21 09:58:53 · 600 阅读 · 0 评论 -
【搜索】:如何用A*搜索算法实现游戏中的寻路功能?
算法解析在【最短路径】:地图软件是如何计算出最优出行路径的?中讲过,如果图非常大,那么Dijkstra最短路径算法的执行耗时会很多。在真实的软件开发中,我们买你对的是超级大的地图和海量的寻路请求,算法的执行效率太低,这显然是无法接受的。实际上,一般情况下,我们都不需要非得求最优解(也就是最短路径)。在权衡路线规划和执行效率的情况下,我们只需要寻求一个次优解就足够了。那如何快速找出一条接近于...转载 2019-06-07 10:42:45 · 936 阅读 · 0 评论 -
【B+树】:MySQL数据库索引是如何实现的?
https://time.geekbang.org/column/article/77830我们都知道,数据库使用索引,会提升效率。那数据库索引是如何实现的呢?底层使用的是什么数据结构和算法?从执行效率方面,我们希望通过索引,查询效率尽可能的高;在存储空间方面,我们希望索引不要消耗太多的空间。1.解决问题的前提是定义清楚问题假设我们有这两个基本的需求:根据某个值查找数据,比如 ...转载 2019-06-04 09:56:15 · 8585 阅读 · 3 评论 -
【并行算法】:如何利用并行处理提高算法的执行效率?
时间复杂度是衡量算法执行效率的一种标准。但时间复杂度并不能跟性能划等号。在真实的软件开发中,即使在不降低时间复杂度的情况下,也可以通过一些优化手段,提升代码的执行效率。毕竟对于实际开发来说,即使是10%的提升,也是非常可观的。当算法无法继续优化的情况下,我们该如何进一步提高执行效率呢?一种非常简单又好用的方法就是并行计算。如何借助并行计算的处理思想对算法进行改造?并行排序假设我们要给大...转载 2019-06-11 10:13:50 · 4236 阅读 · 0 评论 -
【向量空间】:如何实现一个简单的音乐推荐系统
很多人喜爱听歌,现在直接通过音乐App在线就可以听歌。而且,各种音乐App的功能越来越强大,不仅可以自己选歌听,还可以根据你听歌的口味偏好,给你推荐可能喜爱的音乐。有时候推荐的音乐还非常适合你的口味,甚至会惊艳到你!如此智能的一个功能,你知道它是怎么实现的吗?算法解析实际上,要解决这个问题,并不需要特别高深的理论。解决思路的核心思想非常简单、直白,用两句话就能总结出来。找到跟你口味偏好...转载 2019-06-03 10:57:22 · 961 阅读 · 1 评论 -
【概率统计】:如何利用朴素贝叶斯算法过滤垃圾短信?
转载地址:https://time.geekbang.org/column/article/77142上一节我们讲到,如何用位图、布隆过滤器,来过滤重复的数据。今天,我们再讲一个跟过滤相关的问题,如何过滤垃圾短信?垃圾短信和骚扰电话,我想每个人都收到过吧?买房、贷款、投资理财、开发票,各种垃圾短信和骚扰电话,不胜其扰。如果你是一名手机应用开发工程师,让你实现一个简单的垃圾短信过滤功能以及骚...转载 2019-06-03 10:45:40 · 1691 阅读 · 0 评论 -
【字符串匹配基础(中)】:如何实现文本编辑器中的查找功能? BM(Boyer-Moore)算法
文本编辑器中的查找替换功能,我想你应该不陌生吧?比如,我们在 Word 中把一个单词统一替换成另一个,用的就是这个功能。你有没有想过,它是怎么实现的呢?当然,你用上一节讲的 BF 算法和 RK 算法,也可以实现这个功能,但是在某些极端情况下,BF算法性能会退化的比较严重,而 RK 算法需要用到哈希算法,而设计一个可以应对各种类型字符的哈希算法并不简单。对于工业级的软件开发来说,我们希望算法...转载 2019-05-10 09:34:04 · 384 阅读 · 0 评论 -
【深度和广度优先搜索】:如何找出社交网络中的三度好友关系?
上一节我们讲了图的表示方法,讲到如何用有向图、无向图来表示一个社交网络。在社交网络中,有一个六度分割理论,具体是说,你与世界上的另一个人间隔的关系不会超过六度,也就是说平均只需要六步就可以联系到任何两个互不相识的人。一个用户的一度连接用户很好理解,就是他的好友,二度连接用户就是他好友的好友,三度连接用户就是他好友的好友的好友。在社交网络中,我们往往通过用户之间的连接关系,来实现推荐“可能认识的...转载 2019-05-05 21:22:33 · 833 阅读 · 1 评论 -
【散列表(哈希表) Hash Table(中)】:如何打造一个工业级水平的散列表?
通过上一节的学习,我们知道,散列表的查询效率并不能笼统地说成是 O(1)。它跟散列函数、装载因子、散列冲突等都有关系。如果散列函数设计得不好,或者装载因子过高,都可能导致散列冲突发生的概率升高,查询效率下降。在极端情况下,有些恶意的攻击者,还有可能通过精心构造的数据,使得所有的数据经过散列函数之后,都散列到同一个槽里。如果我们使用的是基于链表的冲突解决方法,那这个时候,散列表就会退化为链表,查...转载 2019-04-25 19:46:16 · 362 阅读 · 0 评论 -
[数据结构与算法] 排序(二) 平均时间复杂度O(n^2)
冒泡排序、插入排序、选择排序的时间复杂度均为O(n^2)。插入排序和冒泡排序的时间复杂度相同,都是 O(n^2),在实际的软件开发里,为什么我们更倾向于使用插入排序算法而不是冒泡排序算法呢?冒泡排序冒泡排序只会操作相邻的两个数据。每次冒泡操作都会对相邻的两个元素进行比较,看是否满足大小关系要求。如果不满足就让它俩互换。一轮冒泡会让至少一个元素移动到它应该在的位置,重复 n 轮,就完成...转载 2019-04-13 20:22:51 · 4393 阅读 · 1 评论 -
【二分查找(下)】:如何快速定位IP对应的省份地址?
通过IP地址来查找IP归属地功能,不知道你用过没?没用过也没关系,打开百度,在搜索框里随便输入一个IP地址,就会看到它的归属地。这个功能并不复杂,它是通过维护一个很大的IP地址库来实现。地址库中包括IP地址范围和归属地的对应关系。当我们想要查询202.102.133.13这个IP地址的归属地时,我们就在地址库中搜索,发到IP地址落在[202.102.133.0, 202.102.133.2...转载 2019-04-16 19:41:45 · 1649 阅读 · 0 评论 -
【二分查找(上)】:如何用最省内存的方式实现快速查找功能?
假设我们有 1000 万个整数数据,每个数据占 8 个字节,如何设计数据结构和算法,快速判断某个整数是否出现在这 1000 万数据中? 我们希望这个功能不要占用太多的内存空间,最多不要超过 100MB,你会怎么做呢?带着这个问题,让我们进入今天的内容吧!无处不在的二分思想二分查找是一种非常简单易懂的快速查找算法,生活中到处可见。比如说,我们现在来做一个猜字游戏。我随机写一个 0 到 99 ...转载 2019-04-16 10:11:44 · 382 阅读 · 0 评论 -
[数据结构与算法] 排序(五) 如何实现一个通用的、高性能的排序函数?
几乎所有的编程语言都会提供排序函数,比如 C 语言中 qsort(),C++ STL 中的 sort()、stable_sort(),还有 Java 语言中的 Collections.sort()。在平时的开发中,我们也都是直接使用这些现成的函数来实现业务逻辑中的排序功能。那你知道这些排序函数是如何实现的吗?底层都利用了哪种排序算法呢?基于这些问题,今天我们就来看排序这部分的最后一块内容:如何...转载 2019-04-15 21:33:49 · 455 阅读 · 0 评论 -
【链表】:如何实现最近最少使用策略 LRU(Least Recently Used)缓存淘汰算法?
今天我们来聊聊“链表(Linked list)”这个数据结构。学习链表有什么用呢?为了回答这个问题,我们先来讨论一个经典的链表应用场景,那就是+LRU+缓存淘汰算法。缓存是一种提高数据读取性能的技术,在硬件设计、软件开发中都有着非常广泛的应用,比如常见的+CPU+缓存、数据库缓存、浏览器缓存等等。缓存的大小有限,当缓存被用满时,哪些数据应该被清理出去,哪些数据应该被保留?这就需...转载 2019-04-07 21:21:17 · 620 阅读 · 0 评论 -
[数据结构与算法] 链表
针对链表的插入、删除操作,需要对插入第一个结点和删除最后一个结点的情况进行特殊处理。这样代码实现起来就会很繁琐,不简洁,而且也容易因为考虑不全而出错。如何来解决这个问题呢?技巧三中提到的哨兵就要登场了。哨兵,解决的是国家之间的边界问题。同理,这里说的哨兵也是解决“边界问题”的,不直接参与业务逻辑。如果我们引入哨兵结点,在任何时候,不管链表是不是空,head 指针都会一直指向这个哨兵结点。我们也...原创 2019-03-29 19:39:29 · 382 阅读 · 0 评论 -
[数据结构与算法] 队列
我们知道,CPU 资源是有限的,任务的处理速度与线程个数并不不是线性正相关。相反,过多的线程反而会导致 CPU 频繁切换,处理性能下降。所以,线程池的大小一般都是综合考虑要处理任务的特点和硬件环境,来事先设置的。 当我们向一个固定大小的线程池中请求一个线程时,如果线程池中没有空闲资源了,这个时候线程如何处理这个请求?是拒绝请求还是排队请求?各种策略又是怎么实现的呢? 实际上这些问题...转载 2019-04-04 22:03:42 · 381 阅读 · 0 评论 -
[数据结构与算法] 栈
栈既可以通过数组实现,也可以通过链表来实现。不管基于数组还是链表,入栈、出栈的时间复杂度都为 O(1)。 你应该可以看出来,这 K 次入栈操作,总共涉及了 K 个数据的搬移,以及 K 次 simple-push操作。将 K 个数据搬移均摊到 K 次入栈操作,那每个入栈操作只需要一个数据搬移和一个simple-push 操作。以此类推,入栈操作的均摊时间复杂度就为 O(1)。通过这...原创 2019-04-02 21:28:13 · 2525 阅读 · 0 评论 -
Skip List(跳跃表)原理详解与实现
https://www.cnblogs.com/sky-heaven/p/8334567.html转载 2019-06-23 08:59:44 · 243 阅读 · 0 评论 -
二叉树相关
http://www.cnblogs.com/skywang12345/p/3576328.html树的介绍1. 树的定义树是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:(01) 每个节点有零个或多个子节点;(02) 没有父节点的节点称为根节点;...原创 2019-02-18 21:10:25 · 242 阅读 · 0 评论 -
二叉树的递归和非递归方式的三种遍历
#include <iostream>#include <stack>#include <vector>using namespace std;/* *输入样例 1 2 -1 -1 3 -1 -1 *输入样例 1 2 3 -1 -1 4 -1 -1 5 6 -1 -1 7 -1 -1 *输入样例 1 2 -1 3 -1 -1 4 5 -1...原创 2018-07-06 21:48:21 · 275 阅读 · 0 评论 -
【散列表(哈希表) Hash Table(下)】:为什么散列表和链表经常会一起使用?
你有没有发现,有两种数据结构,散列表和链表,经常会被放在一起使用。在链表那一节,我讲到如何用链表来实现 LRU 缓存淘汰算法,但是链表实现的 LRU 缓存淘汰算法的时间复杂度是 O(n),当时我也提到了,通过散列表可以将这个时间复杂度降低到 O(1)。在跳表那一节,我提到 Redis 的有序集合是使用跳表来实现的,跳表可以看作一种改进版的链表。当时我们也提到,Redis 有序集合不仅使用了...转载 2019-04-25 21:07:09 · 196 阅读 · 0 评论 -
[数据结构与算法] 排序(三) 平均时间复杂度O(nlogn)
时间复杂度为 O(nlogn) 的排序算法,归并排序和快速排序。这两种排序算法适合大规模的数据排序。算法 是否原地排序 是否稳定 最好 最坏 平均 归并排序 否 是 O(nlogn) O(nlogn) O(nlogn) 快速排序 是 否 O(nlogn) O(n^2) O(nlogn) 归并排...转载 2019-04-14 20:21:22 · 21116 阅读 · 3 评论 -
【红黑树(下)】:掌握这些技巧,你也可以实现一个红黑树
红黑树是一个让我又爱又恨的数据结构,“爱”是因为它稳定、高效的性能,“恨”是因为实现起来实在太难了。我今天讲的红黑树的实现,对于基础不太好的同学,理解起来可能会有些困难。但是,我觉得没必要去死磕它。我为什么这么说呢?因为,即便你将左右旋背得滚瓜烂熟,我保证你过不几天就忘光了。因为,学习红黑树的代码实现,对于你平时做项目开发没有太大帮助。对于绝大部分开发工程师来说,这辈子你可能都用不着亲手写一个...转载 2019-05-02 10:32:31 · 296 阅读 · 0 评论