| 作 者: | 王争 |
| 出版社: | 人民邮电出版社 |
| 丛编项: | |
| 版权说明: | 本书为公共版权或经版权方授权,请支持正版图书 |
| 标 签: | 暂缺 |
| ISBN | 出版时间 | 包装 | 开本 | 页数 | 字数 |
|---|---|---|---|---|---|
| 未知 | 暂无 | 暂无 | 未知 | 0 | 暂无 |
《数据结构与算法之美(全彩印刷)》
目录
第 1章 复杂度分析 1
1.1 复杂度分析(上):如何分析代码的执行效率和资源消耗 2
1.1.1 复杂度分析的意义 2
1.1.2 大O复杂度表示法 2
1.1.3 时间复杂度分析方法 4
1.1.4 几种常见的时间复杂度量级 5
1.1.5 空间复杂度分析方法 7
1.1.6 内容小结 7
1.1.7 思考题 8
1.2 复杂度分析(下):详解最好、最坏、平均、均摊这4种时间复杂度 8
1.2.1 最好时间复杂度和最坏时间复杂度 8
1.2.2 平均时间复杂度 9
1.2.3 均摊时间复杂度 10
1.2.4 内容小结 11
1.2.5 思考题 12
第 2章 数组、链表、栈和队列 13
2.1 数组(上):为什么数组的下标一般从0开始编号 14
2.2 数组(下):数据结构中的数组和编程语言中的数组的区别 19
2.3 链表(上):如何基于链表实现LRU缓存淘汰算法 23
2.4 链表(下):借助哪些技巧可以轻松地编写链表相关的复杂代码 30
2.5 栈:如何实现浏览器的前进和后退功能 35
2.6 队列:如何实现线程池等有限资源池的请求排队功能 40
第3章 递归、排序、二分查找 46
3.1 递归:如何用3行代码找到“Z终推荐人” 47
3.2 尾递归:如何借助尾递归避免递归过深导致的堆栈溢出 53
3.3 排序算法基础:从哪几个方面分析排序算法 55
3.4 O(n2)排序:为什么插入排序比冒泡排序更受欢迎 58
3.5 O(nlogn)排序:如何借助快速排序思想快速查找第K大元素 64
3.6 线性排序:如何根据年龄给100万个用户排序 72
3.7 排序优化:如何实现一个高性能的通用的排序函数 78
3.8 二分查找:如何用Z省内存的方式实现快速查找功能 80
3.9 二分查找的变体:如何快速定位IP地址对应的归属地 85
第4章 哈希表、位图和哈希算法 91
4.1 哈希表(上):Word软件的单词拼写检查功能是如何实现的 92
4.2 哈希表(中):如何打造一个工业级的哈希表 96
4.3 哈希表(下):如何利用哈希表优化LRU缓存淘汰算法 101
4.4 位图:如何实现网页“爬虫”中的网址链接去重功能 106
4.5 哈希算法:如何防止数据库脱库后用户信息泄露 111
第5章 树 117
5.1 树和二叉树:什么样的二叉树适合用数组存储 118
5.2 二叉查找树:相比哈希表,二叉查找树有何优势 122
5.3 平衡二叉查找树:为什么红黑树如此受欢迎 128
5.4 递归树:如何借助树求递归算法的时间复杂度 131
5.5 B+树:MySQL数据库索引是如何实现的 135
第6章 堆 141
6.1 堆:如何维护动态集合的最值 142
6.2 堆排序:为什么说堆排序没有快速排序快 147
6.3 堆的应用:如何快速获取Top 10热门搜索关键词 151
第7章 跳表、并查集、线段树和树状数组 157
7.1 跳表:Redis中的有序集合类型是如何实现的 158
7.2 并查集:路径压缩和按秩合并这两个优化是否冲突 163
7.3 线段树:如何查找猎聘网中积分排在第K位的猎头 168
7.4 树状数组:如何实现一个高性能、低延迟的实时排行榜 174
第8章 字符串匹配算法 179
8.1 BF算法:编程语言中的查找、替换函数是怎样实现的 180
8.2 RK算法:如何借助哈希算法实现高效的字符串匹配 182
8.3 BM算法:如何实现文本编辑器中的查找和替换功能 185
8.4 KMP算法:如何借助BM算法理解KMP算法 194
8.5 Trie树:如何实现搜索引擎的搜索关键词提示功能 198
8.6 AC自动机:如何用多模式串匹配实现敏感词过滤 204
第9章 图 210
9.1 图的表示:如何存储微博、微信等社交网络中的好友关系 211
9.2 深度优先搜索和广度优先搜索:如何找出社交网络中的三度好友关系 216
9.3 拓扑排序:如何确定代码源文件的编译依赖关系 221
9.4 单源Z短路径:地图软件如何“计算”Z优出行路线 225
9.5 多源Z短路径:如何利用Floyd算法解决传递闭包问题 231
9.6 启发式搜索:如何用A*算法实现游戏中的寻路功能 233
9.7 Z小生成树:如何随机生成游戏中的迷宫地图 238
9.8 Z大流:如何解决单身交友联谊中的Z多匹配问题 245
第 10章 贪心、分治、回溯和动态规划 251
10.1 贪心算法:如何利用贪心算法实现霍夫曼编码 252
10.2 分治算法:谈一谈大规模计算框架MapReduce中的分治思想 256
10.3 回溯算法:从电影《蝴蝶效应》中学习回溯算法的核心思想 260
10.4 初识动态规划:如何巧妙解决“双11”购物时的凑单问题 264
10.5 动态规划理论:彻底理解最优子结构、无后效性和重复子问题 272
10.6 动态规划实战:如何实现搜索引擎中的拼写纠错功能 278
第 11章 数据结构和算法实战 284
11.1 实战1:剖析Redis的常用数据类型对应的数据结构 285
11.2 实战2:剖析搜索引擎背后的经典数据结构和算法 288
11.3 实战3:剖析微服务鉴权和限流背后的数据结构和算法 293
11.4 实战4:用学过的数据结构和算法实现短网址服务 299
附录A 思考题答案 304
《设计模式之美》
第 1章概述 1
1.1 为什么学习代码设计 2
1.1.1 编写高质量的代码 2
1.1.2 应对复杂代码的开发 2
1.1.3 程序员的基本功 3
1.1.4 职场发展的必备技能 4
1.1.5 思考题 4
1.2 如何评价代码质量 4
1.2.1 可维护性(maintainability) 5
1.2.2 可读性(readability) 6
1.2.3 可扩展性(extensibility) 6
1.2.4 灵活性(flexibility) 6
1.2.5 简洁性(simplicity) 7
1.2.6 可复用性(reusability) 7
1.2.7 可测试性(testability) 7
1.2.8 思考题 8
1.3 如何写出高质量代码 8
1.3.1 面向对象 8
1.3.2 设计原则 8
1.3.3 设计模式 9
1.3.4 代码规范 9
1.3.5 重构技巧 10
1.3.6 思考题 11
1.4 如何避免过度设计 11
1.4.1 代码设计的初衷是提高代码质量 11
1.4.2 代码设计的原则是“先有问题,后有方案” 12
1.4.3 代码设计的应用场景是复杂代码 12
1.4.4 持续重构可有效避免过度设计 12
1.4.5 不要脱离具体的场景谈代码设计 13
1.4.6 思考题 13
第 2章面向对象编程范式 14
2.1 当我们在谈论面向对象时,到底在谈论什么 15
2.2 封装、抽象、继承和多态为何而生 17
2.3 如何进行面向对象分析、面向对象设计和面向对象编程 25
2.4 面向对象编程与面向过程编程和函数式编程之间的区别 35
2.5 哪些代码看似面向对象编程风格,实则面向过程编程风格 45
2.6 基于“贫血”模型的传统开发模式是否违背OOP 51
2.7 接口和抽象类:如何使用普通类模拟接口和抽象类 59
2.8 基于接口而非实现编程:有没有必要为每个类都定义接口 65
2.9 组合优于继承:什么情况下可以使用继承 70
第3章设计原则 75
3.1 单一职责原则:如何判定某个类的职责是否单一 76
3.2 开闭原则:只要修改代码,就一定违反开闭原则吗 79
3.3 里氏替换原则:什么样的代码才算违反里氏替换原则 86
3.4 接口隔离原则:如何理解该原则中的“接口” 89
3.5 依赖反转原则:依赖反转与控制反转、依赖注入有何关系 97
3.6 KISS原则和YAGNI原则:二者是一回事吗 100
3.7 DRY原则:相同的两段代码就一定违反DRY原则吗 104
3.8 LoD:如何实现代码的“高内聚、低耦合” 110
第4章代码规范 117
4.1 命名与注释:如何精准命名和编写注释 118
4.2 代码风格:与其争论标准,不如团队统一 121
4.3 编程技巧:小技巧,大作用,一招提高代码的可读性 123
第5章重构技巧 130
5.1 重构四要素:目的、对象、时机和方法 131
5.2 单元测试:保证重构不出错的有效手段 133
5.3 代码的可测试性:如何编写可测试代码 139
5.4 解耦:哪些方法可以用来解耦代码 147
5.5 重构案例:将ID生成器代码从“能用”重构为“好用” 150
第6章创建型设计模式 166
6.1 单例模式(上):为什么不推荐在项目中使用单例模式 167
6.2 单例模式(下):如何设计实现一个分布式单例模式 177
6.3 工厂模式(上):如何解耦复杂对象的创建和使用 180
6.4 工厂模式(下):如何设计实现一个依赖注入容器 188
6.5 建造者模式:什么情况下必须用建造者模式创建对象 194
6.6 原型模式:如何快速复制(clone)一个哈希表 200
第7章结构型设计模式 208
7.1 代理模式:代理模式在RPC、缓存和监控等场景中的应用 209
7.2 装饰器模式:剖析Java IO类库的底层设计思想 213
7.3 适配器模式:如何利用适配器模式解决代码的不兼容问题 219
7.4 桥接模式:如何将M×N的继承关系简化为M+N的组合关系 230
7.5 门面模式:如何设计接口以兼顾接口的易用性和通用性 231
7.6 组合模式:一种应用在树形结构上的特殊设计模式 233
7.7 享元模式:如何利用享元模式降低系统的内存开销 239
第8章行为型设计模式 249
8.1 观察者模式:如何实现一个异步非阻塞的EventBus框架 250
8.2 模板方法模式(上):模板方法模式在JDK、Servlet、JUnit中的应用 261
8.3 模板方法模式(下):模板方法模式与回调有何区别和联系 267
8.4 策略模式:如何避免冗长的if-else和switch-case语句 273
8.5 职责链模式:框架中的过滤器、拦截器和插件是如何实现的 282
8.6 状态模式:游戏和工作流引擎中常用的状态机是如何实现的 297
8.7 迭代器模式(上):为什么要用迭代器遍历集合 306
8.8 迭代器模式(下):如何实现一个支持快照功能的迭代器 315
8.9 访问者模式:为什么支持双分派的编程语言不需要访问者模式 320
8.10 备忘录模式:如何优雅地实现数据防丢失、撤销和恢复功能 330
8.11 命令模式:如何设计实现基于命令模式的手游服务器 334
8.12 解释器模式:如何设计实现一个自定义接口告警规则的功能 337
8.13 中介模式:什么时候使用中介模式?什么时候使用观察者模式? 343