本文目录导航:
如何评估极客期间上王争的「数据结构与算法之美」的爆火?
在极客期间平台上,王争的《数据结构与算法之美》一书为何备受注目并引发热议?
时代似乎在向咱们收回信号:在这个信息爆炸的时代,虽然实体书如亚马逊上的《数据结构与算法之美》以74元的亲民多少钱和黑白版面吸引着眼球,但面对海量的在线课程,人们似乎更偏差于听觉的方便。
付费课程,尤其是王争的解说,似乎为那些盼望常识但又不愿静下心来浏览的听众提供了一剂“心灵鸦片”。
他们花钱凝听,似乎在短期间内找到了处置疑问的捷径,似乎焦虑症患者持久地沉迷在“治愈”之中。
但是,这种持久的满足感并不能代替深入学习,事实的应战和下一次性的焦虑依然期待着他们。
《数据结构与算法之美》的魅力在于它将复杂的实践常识转化为活泼的故事,让听者在轻松的气氛中领略算法的精妙。
但是,书籍的浏览体验却无法被方便地同等于听觉教授。
书籍的深度和系统性,是那些情愿静心研读的人才干收获的宝藏。
在当今快节拍的社会,如何在听与读之间找到平衡,成为了一个值得讨论的疑问。
虽然在线听书在某种水平上满足了公众的即时需求,但它并不能代替对常识的深化了解和常年积攒。
真正的学习,是须要期间和耐烦去积淀的,就像那本静静躺在书架上的黑白算法书,期待着有心人的打开和探求。
所以,王争的课程或许能临时缓解咱们的焦虑,但唯有真正去把握和运用那些“算法之美”,才干在常识的陆地中游刃缺乏,抵御下一次性的应战。
学习数据结构,有哪些值得介绍的好书
作者:向小刚链接:起源:知乎著述权归作者一切。
商业转载请咨询作者取得授权,非商业转载请注明出处。
1. CLRS 算法导论 算法百科全书,只做了前面十几章的习题,便觉得获益良多。
2. Algorithms 算法概论 短小精悍,别据一格,准经典之作。
一个坏信息: 同算法导论,该书没有习题答案。
好信息:习题很经典,难度也适中,只要花点点期间自己也都能做进去。
不好也不坏的信息:我正在写习题的答案,已成功前三章,还剩九章约二百道题,顺利的话二个月之后颁布。
另有中文版名《算法概论》,我没看过,不知道翻译得怎样样。
假设有心的话,还是尽量看原版吧,其实看原版与看中文版破费期间不会相差很大,由于大局部期间其实都破费在做习题上了。
dr. dobbs essential books on Algorithm and daba structure3. Algorithm Design 算法设计 很经典的一本书,很久之前看的,遗憾的是如今除了就记得它很经典之外其它都忘光了。
4. SICP 计算机程序的结构和解释 六星之书无需多言,虽然这不是一本讲算法的书,但看完此书有助于你更深化的了解什么是递归。
我不时很强调习题,看完此书后你至少应该做完前四章的太局部习题。
否则那是你的遗憾,也是作者的遗憾。
5. Concrete Mathematics 详细数学 有人说看TAOCP之前应该先弄清楚这本书的内容,要真是如此的话那我恐怕是看不到TAOCP了。
零系统碎的看了一大半,很多物品都没有期间来好好消化。
假设你是刚进大学不久的本科生,有着大把的可自在摆布期间,那你幸运又幸福了,花上几个月期间好好的读一下此书吧,收获相对大于你的希冀值。
6. Introduction to The Design and Analysis of Algorithms 算法设计与剖析基础 很幽默的一本算法书,有许多在别的书上找不到的趣题,看完此书相对能让你大开眼界,真实是一本居家游览,面试装逼的必备佳作。
7. 编程之美--微软技术面试心得 虽说是一本面试书,但假设把前面十几页扯掉的话,我更情愿把它看作是一本解说题思想的算法小品。
在书中,作者通常是给出一个平时解法,而后再一次性又一次性的提升改良,你可以很清楚的看到基本的算法设计思想是如何获取运用以处置实践疑问的。
假设你曾经有了一些算法的基础,看完本书应该能使你的算法运行才干获取肯定的提高。
另外,本书活泼幽默,也雷同适宜于初学者。
8. Fundamentals of Algorithmics 算法基础 也是很久之前在学校图书馆借来看的,内容记不太清楚了,只隐约记得此书的灵活布局章节犹为出彩。
应该是很经典的一本书,团体认为足以和算法导论等所谓当世经典平分春色,但是怎样似乎被人提到的不多,或许是我见多识广了。
9. How to solve it 怎样解题 二十世纪最平凡的数学思想家之一波利亚的力作,讲普通性的解题方法:怎样意识疑问,怎样转换疑问,怎样处置疑问,如何在疑问中获取启示,如何找到一个通往答案的方向。
10. Programming interviews exposed 程序员面试攻略 一本消遣之作。
团体认为要比国际的某“XXX面试宝典”纯正一些,至少也有一些启示性的内容,而不单单是面试题解库。
11. Programming Pearls 编程珠玑 学习算法不只须要像Alogrithms,算法导论这样的重量级的内功心法,像《编程之美》、《编程珠玑》这样的轻量级的轻功身法也必无法少。
前些年网上不是很盛行像“给你10亿个数,找到最大的n个”或许“给你10亿个数,找产生次数最多的那个数”之类的网络面试题吗?看了此书你就知道怎样处置了。
相比于《编程之美》来说,本书中的示例技巧性略低一些,但是也更有实践运行价值一些。
12. 算法艺术与信息学竞赛 假设算法导论是九阳神功,那这本无疑就是九阴真经。
本书是专为加入一些诸如ACM之类程序设计较量的同窗而写的,江湖人称“黑书”。
外面讲的都是一些在编程较量中罕用的算法、数据结构,以及一些数论和计算几何等。
我虽然并不搞竞赛,但也从此书中受益颇多。
13. An Introduction to Probability Theory and Its Applications 预备看的,如今才发现概率论有如许关键,惋惜本科的时刻没有好好学。
前不久一个同窗识我个疑问,我半天弄了一个程序给他,他说:这里就不是相相关数么,Excel一下就完事!我晕,我还真不知道那就是相相关数。
14. Numerical Analysis 这本的作者是Richard L. Burden,J. Douglas Faires 数值剖析,讨论各种数值算法,比如插值、拟合、积分、微分方程的求解、线性和非线性方程组求解等。
预备详细看。
15. TAOCP 计算机程序设计艺术 传说中的TAOCP,说的人多,看的人少。
TAOCP四卷可谓是算法藏经阁中的易筋经或许是少林七十二绝技。
天下武学,尽出少林,天下算法,尽出TAOCP也。
数据结构与算法之美笔记——散列表(上)
摘要:
咱们曾经知道随机访问数组元素期间复杂度只要,效率极高,当咱们想应用数组的这个个性时就须要将元素下标与存储信息对应。
例如,一个商店只要四件商品,依次编号 0 至 3,这样就可以将四件商品信息依照编号对应下标的模式存储到数组中,依据编号就可以极速从数组中找到相应商品信息。
假设一段期间之后,商店盈利并且从新进货 100 件商品,商家想对少量商品在编号上辨别类别,这时刻须要经常使用类别编号加顺序编号的模式标识每件商品,这种编号变得复杂,并不能间接对应数组下标,此时的商品编号又该如何对应数组下标以成功极速查找商品的配置?这时刻咱们可以将类别编号去除之后依照顺序编号对应数组下标,雷同也能享用数组高效率随机访问的福利。
这个例子中,商品编号称为「 键 」或「 关键字 」,将键转化为数组对应下标的方法就是「 散列函数 」或「 Hash 函数 」,由散列函数生成的值叫做「 散列值 」或「 Hash 值 」,而这样的数组就是散列表。
从散列表的原理来看,数据经过散列函数计算获取散列值是关键,这个步骤中散列函数又是其中的外围,一个散列函数须要遵守以下三个准则。
由于散列函数生成的散列值对应数组下标,而数组下标就是非负整数,所以须要满足第一个准则;两个相等的数据经过散列算法获取的散列值必需相等,否则应用散列值在散列表中查找数据就无从谈起;至于第三个准则虽然在道理之中,却不那么容易做到,即使是被宽泛运用的散列算法也会产生散列值抵触的状况,造成无法满足第三个准则。
散列函数作为散列表的外围局部,肯定不能拖散列表的口头效率后腿,毕竟散列表的查问、拔出和删除操作都须要经过散列函数,所以散列函数不能太复杂,口头效率不能太低。
由于散列函数无法防止地都会产生散列抵触状况,散列函数要尽量降低散列抵触,使散列值能够平均地散布在散列表中。
处置散列抵触关键有「 放开寻址 」(open addressing)和「 链表法 」(chaining)两类方法。
放开寻址法是指拔出操作时,当生成的散列值对应槽位曾经被其余数据占用,就探测闲暇位置供拔出经常使用,其中探测方法又分为「 线性探测 」(Linear Probing)、「 二次探测 」(Quadratic Probing)和「 双重散列 」(Double hashing)三种。
线性探测是其中较为方便的一种,这种探测模式是当遇到散列抵触的状况就顺序查找(查找到数组尾部时转向数组头部继续查找),直到查找到空槽将数据拔出。
当启动查找操作时,也是雷同的操作,应用散列值从散列表中取出对应元素,与指标数据比对,假设不相等就继续顺序查找,直到查找到对应元素或遇到空槽为止,最坏状况下查找操作的期间复杂度或许会降低为 。
散列表除了允许拔出和查找操作外,当然也允许删除操作,不过并不能将需删除的元素置为空。
假设删除操作是将元素置为空的话,查找操作遇到空槽就会完结,存储在被删除元素之后的数据就或许无法正确查找到,这时的删除操作应该经常使用标志的模式,而不是经常使用将元素置空,当查找到被标识已删除的元素将继续查找,而不是就此中止。
线性探测是一次性一个元素的探测,二次探测就是经常使用都是线性探测的二次方步长探测。
例如线性探测是 ,那二次探测对应的就是 。
双重探测是当第一个散列函数抵触时经常使用第二个散列函数运算散列值,应用这种模式探测。
例如,当抵触时,就经常使用计算散列值,假设再抵触就经常使用计算散列值,依此类推。
关于散列表的空位多少经常使用「 装载因子 」(load factor)示意,装载因子满足数学相关 ,也就是说装载因子越大,散列表的闲暇空间越小,散列抵触的或许性也就越大,普通咱们会坚持散列表有肯定比例的闲暇空间。
为了坚持散列表肯定比例的闲暇空间,在装载因子抵达肯定阈值时须要对散列表数据启动搬移,但散列表搬移比拟耗时。
你可以试想下这样的步骤,在放开一个新的更大的散列表空间后,须要将旧散列表的数据从新经过散列函数生成散列值,再存储到新散列表中,想想都觉得费事。
散列表搬移的操作必需会降低散列表的操作效率,那能不能对这一环节启动改良?其实可以将低效的扩容操作摊派至拔出操作,当装载因子到达阈值时不一次性性启动散列表搬移,而是在每次拔出操作时将一个旧散列表数据搬移至新散列表,这样搬移操作的口头效率获取了提高,拔出操作的期间复杂度也依然能坚持的高效。
当新旧两个散列表同时存在时查问操作就要略作修正,需先在新散列表中查问,假设没有查找到指标数据再到旧散列表中查找。
当然,假设你对内存有更高效的应用要求,可以在装载因子降低至某一阈值时对散列表启动缩容处置。
除了放开寻址之外,还可以经常使用链表法处置散列抵触的疑问。
散列值对应的槽位并不间接存储数据,而是将数据存储在槽位对应的链表上,当启动查找操作时,依据散列函数计算的散列值找到对应槽位,再在槽位对应的链表上查找对应数据。
链表法操作的期间复杂度与散列表槽位和数据在槽位上的散布状况无关,假定有 n 个数据平均散布在 m 个槽位的散列表上,那链表法的期间复杂度为 。
链表法可以不用像放开寻址一样关心装载因子,但须要留意散列函数对散列值的计算,使链表结点能够尽或许平均地散布在散列表槽位上,防止散列表退步为链表。
有时黑客甚至会精心制作数据,应用散列函数制作散列抵触,使数据集中某些槽位上,形成散列表性能的极度退步。
面对这样的恶意行为散列表只能坐以待毙吗?其实不然,当槽位上的链表过长时,可以将其改形成之前学习过的跳表等,链表变革为跳表后查问的期间复杂度也只是退步为 ,依然是可以接受的范畴。
链表法在存储应用上比放开寻址愈加高效,不用提早放开存储空间,当有新数据时放开一个新的结点就行。
而且链表法对装载因子也不那么敏感,装载因子的增高也只是象征着槽位对应的链表更长而已,链表增长也有将链表变革为跳表等结构的应答战略,所以链表法在装载因子超越 1 的状况下都可坚持高效。
放开寻址不存在像链表法一样有链表过长而造成效率降低的烦恼,不过装载因子是放开寻址的晴雨表,装载因子过高会形成散列抵触机率的回升,放开寻址就须要不时探测闲暇位置,算法的口头老本会不时被提高。
而且在删除操作时只能将数据先标志为删除,关于频繁增删的数据效率会遭到影响。
当然也可以在这种危险产生行启动散列表的灵活扩容,不过这样就会产生少量闲暇的存储空间,造成存储的应用效率过低,这种现象在数据量越大的状况下越显著。
所以放开寻址比拟实用于数据量较小的状况。
链表法关于散列抵触的处置愈加灵敏,同时对存储空间的应用效率也更高,但链表结点除了存储数据外还须要存储指针,假设存储数据较小指针占用的存储甚至会造成全体存储翻倍的状况,但存储数据较大时指针占用的存储也就可以疏忽不计,所以链表法较适宜存储数据对象较大,但频繁的增删操作不会对链表法形成显著的影响。
由于这样的特点,链表法愈加适宜大数据量,或许数据对象较大的时刻,假设数据操作频繁,那链表法更是不二之选。
散列表由数组裁减而来,经常使用散列函数将键计算为散列值,散列值对应数据存储的数组下标。
虽然散列表的口头效率较高,但会有散列抵触的疑问,可以经过放开寻址法和链表法处置此疑问。
放开寻址存储应用效率较低,实用数据量较小并且增删不频繁的状况,假设数据量较大,增删频繁的状况愈加实用链表法,相对之下链表法愈加普适。