本书从一系列有趣的生活实例出发,全面介绍了构造算法的基础方法及其广泛应用,生动展现了算法的趣味性和实用性。书中介绍了算法在多个领域的应用,如图像处理、物理实验、计算机图形学、数字音频处理、机器学习等。其中,既有各种大名鼎鼎的算法,如神经网络、遗传算法、离散傅里叶变换算法、KNN、贝叶斯算法,也有不起眼的排序和概率计算算法。本书讲解浅显易懂而不失深度和严谨,对程序员有很大的启发意义。书中所有示例都与生活息息相关,充分地展现了算法解决问题的本质,让你爱上算法,乐在其中。本书在第1版的基础上新增了图像处理算法、游戏开发中检测碰撞常用的分离轴 (SAT)算法、垃圾邮件过滤相关的算法、中文分词算法、限流算法、手写数字识别和变声器等,进一步提升趣味性。
本书适合软件开发人员、编程和算法爱好者以及计算机专业的学生阅读。
1.内容丰富,条理清晰,包罗万象。不仅包含常见数据结构算法、数值计算方法、机器学习算法、运筹优化算法,也包括图像、安全等领域的专用处理算法。
2.软件行业深耕多年的高口碑算法大咖详细讲解实用可靠的知识点,带你玩转算法,尽享算法的乐趣。
3.趣味性、理论性与实践性并存。书中有代码实现,有应用实例,并巧妙结合生活实际,充满乐趣,让学习更轻松、更有效。
王晓华
硕士毕业于华中科技大学,曾任职于中兴通讯上海研发中心,担任软件工程师、开发经理和PON业务软件负责人,目前兼任步威软件技术有限公司CTO和Boolan软件技术首席咨询师。
前言 iii
致谢 vi
第 1章 图像处理的几个简单算法 1
1.1 灰度(灰阶)算法 1
1.1.1 平均值法 2
1.1.2 最大值法 2
1.1.3 (经验)权重法 2
1.2 二值化(阈值)算法 3
1.2.1 Wellner 1993算法原理 4
1.2.2 Wellner 1993算法实现 6
1.2.3 Bradley & Roth算法原理 8
1.2.4 Bradley & Roth算法实现 10
1.3 考眼力游戏与图像求差 12
1.4 梯度算法与图像清晰度 13
1.4.1 Brenner梯度函数 14
1.4.2 EVA梯度函数 15
1.4.3 Tenengrad梯度函数 16
1.4.4 Laplacian梯度函数 17
1.5 边缘检测与落雪效果 18
1.5.1 梯度函数与边缘检测 19
1.5.2 研究积雪的效果 20
第 2章 分离轴算法与碰撞检测 23
2.1 计算几何基础 23
2.1.1 向量的加法和减法 23
2.1.2 向量的点积 24
2.1.3 法向量 24
2.1.4 投影 25
2.2 分离轴定理 25
2.2.1 算法原理 26
2.2.2 基本数据模型 26
2.2.3 如何找分离轴 27
2.2.4 计算投影 29
2.2.5 最后,碰撞检测 30
2.3 总结 31
2.4 参考资料 31
第3章 垃圾邮件过滤与贝叶斯分类算法 32
3.1 贝叶斯定理 32
3.1.1 概率和条件概率 33
3.1.2 有多个条件时的条件概率 33
3.2 贝叶斯理论 33
3.2.1 贝叶斯理论原理 34
3.2.2 贝叶斯分类器原理 34
3.2.3 贝叶斯理论的应用示例 34
3.2.4 贝叶斯理论的使用方法 35
3.3 垃圾邮件分类器原理 36
3.3.1 第 一步:准备工作 36
3.3.2 第二步:训练分类器 38
3.3.3 第三步:应用分类器 40
3.4 总结 42
3.5 参考资料 42
第4章 最大匹配算法——最简单的中文分词算法 43
4.1 最大匹配算法 43
4.1.1 正向最大匹配算法 43
4.1.2 逆向最大匹配算法 45
4.1.3 算法分析 46
4.2 算法实现 46
4.2.1 词典及词典匹配 46
4.2.2 正向最大匹配算法实现 47
4.2.3 逆向最大匹配算法实现 48
4.3 总结 50
4.4 参考资料 50
第5章 3个水桶等分8升水的问题 51
5.1 问题与求解思路 52
5.2 建立数学模型 53
5.2.1 状态的数学模型与状态树 53
5.2.2 倒水动作的数学模型 54
5.3 搜索算法 55
5.3.1 状态树的遍历 55
5.3.2 剪枝和重复状态判断 56
5.4 算法实现 57
5.5 总结 59
5.6 参考资料 59
第6章 妖怪与和尚过河问题 60
6.1 问题与求解思路 61
6.2 建立数学模型 61
6.2.1 状态的数学模型与状态树 62
6.2.2 过河动作的数学模型 62
6.3 搜索算法 64
6.3.1 状态树的遍历 65
6.3.2 剪枝和重复状态判断 66
6.4 算法实现 66
6.5 总结 68
6.6 参考资料 68
第7章 稳定匹配与舞伴问题 69
7.1 稳定匹配问题 69
7.1.1 什么是稳定匹配 69
7.1.2 Gale-Shapley 算法原理 70
7.2 Gale-Shapley 算法的应用实例 72
7.2.1 算法实现 72
7.2.2 改进优化:空间换时间 75
7.3 有多少稳定匹配 76
7.3.1 穷举所有的完美匹配 77
7.3.2 不稳定因素的判断算法 78
7.3.3 穷举的结果 79
7.4 二部图与二分匹配 80
7.4.1 最大匹配与匈牙利算法 81
7.4.2 带权匹配与Kuhn-Munkres算法 84
7.5 总结 89
7.6 参考资料 90
第8章 爱因斯坦的思考题 91
8.1 问题的答案 92
8.2 分析问题的数学模型 92
8.2.1 基本模型定义 92
8.2.2 线索模型定义 94
8.3 算法设计 95
8.3.1 穷举所有的组合结果 95
8.3.2 利用线索判定结果的正确性 97
8.4 总结 99
8.5 参考资料 100
第9章 项目管理与图的拓扑排序 101
9.1 AOV网和AOE网 103
9.2 拓扑排序 104
9.2.1 拓扑排序的基本过程 104
9.2.2 按照活动开始时间排序 104
9.3 关键路径算法 107
9.3.1 什么是关键路径 108
9.3.2 计算关键路径的算法 109
9.4 总结 112
9.5 参考资料 113
第 10章 限流算法与两个桶 114
10.1 漏桶算法 114
10.2 令牌桶算法 117
10.2.1 原理 117
10.2.2 算法细节 117
10.2.3 CRateLimiter类 119
10.2.4 测试CRateLimiter类 120
10.3 总结 122
10.4 参考资料 122
第 11章 算法与历法 123
11.1 格里历(公历)生成算法 123
11.1.1 格里历的历法规则 123
11.1.2 今天星期几 124
11.1.3 生成日历的算法 129
11.1.4 日历变更那点事儿 130
11.2 二十四节气的天文学计算 132
11.2.1 二十四节气的起源 132
11.2.2 二十四节气的天文学定义 132
11.2.3 VSOP-82/87行星理论 135
11.2.4 误差修正——章动 138
11.2.5 误差修正——光行差 140
11.2.6 用牛顿迭代法计算二十四节气 141
11.3 农历朔日(新月)的天文学计算 144
11.3.1 日月合朔的天文学定义 144
11.3.2 ELP-2000/82月球理论 145
11.3.3 误差修正——地球轨道离心率修正 146
11.3.4 误差修正——黄经摄动 147
11.3.5 月球地心视黄经和最后的修正——地球章动 148
11.3.6 用牛顿迭代法计算日月合朔 149
11.4 农历的生成算法 150
11.4.1 中国农历的起源与历法规则 151
11.4.2 中国农历的推算 156
11.4.3 一个简单的“年历” 164
11.5 总结 164
11.6 参考资料 165
第 12章 实验数据与曲线拟合 166
12.1 曲线拟合 166
12.1.1 曲线拟合的定义 166
12.1.2 简单线性数据拟合的例子 166
12.2 最小二乘法曲线拟合 167
12.2.1 最小二乘法原理 168
12.2.2 高斯消元法求解方程组 169
12.2.3 最小二乘法解决“速度与加速度”实验 170
12.3 三次样条曲线拟合 171
12.3.1 插值函数 172
12.3.2 样条函数的定义 172
12.3.3 边界条件 173
12.3.4 推导三次样条函数 174
12.3.5 追赶法求解方程组 177
12.3.6 三次样条曲线拟合算法实现 179
12.3.7 三次样条曲线拟合的效果 181
12.4 总结 183
12.5 参考资料 183
第 13章 非线性方程与牛顿迭代法 184
13.1 非线性方程求解的常用方法 184
13.1.1 公式法 184
13.1.2 二分逼近法 185
13.2 牛顿迭代法的数学原理 186
13.3 用牛顿迭代法求解非线性方程的实例 187
13.3.1 导函数的求解与近似公式 187
13.3.2 算法实现 188
13.4 参考资料 188
第 14章 计算几何与计算机图形学 189
14.1 计算几何的基本算法 189
14.1.1 点与矩形的关系 190
14.1.2 点与圆的关系 190
14.1.3 矢量的基础知识 191
14.1.4 点与直线的关系 193
14.1.5 直线与直线的关系 194
14.1.6 点与多边形的关系 196
14.2 直线生成算法 199
14.2.1 什么是光栅扫描转换 200
14.2.2 数值微分法 200
14.2.3 Bresenham算法 202
14.2.4 对称直线生成算法 204
14.2.5 两步算法 205
14.2.6 其他直线生成算法 207
14.3 圆生成算法 208
14.3.1 圆的八分对称性 208
14.3.2 中点画圆算法 209
14.3.3 改进的中点画圆算法——Bresenham算法 210
14.3.4 正负判定画圆法 211
14.4 椭圆生成算法 212
14.4.1 中点画椭圆算法 213
14.4.2 Bresenham椭圆生成算法 216
14.5 多边形区域填充算法 218
14.5.1 种子填充算法 219
14.5.2 扫描线填充算法 224
14.5.3 改进的扫描线填充算法 231
14.5.4 边界标志填充算法 235
14.6 总结 238
14.7 参考资料 238
第 15章 音频频谱和均衡器与傅里叶变换算法 239
15.1 实时频谱显示的原理 239
15.2 离散傅里叶变换 240
15.2.1 什么是傅里叶变换 241
15.2.2 傅里叶变换原理 241
15.2.3 快速傅里叶变换算法的实现 245
15.3 傅里叶变换与音频播放的实时频谱显示 247
15.3.1 频域数值的特点分析 247
15.3.2 从音频数据到功率频谱 248
15.3.3 音频播放时实时频谱显示的例子 251
15.4 破解电话号码的小把戏 253
15.4.1 拨号音的频谱分析 253
15.4.2 根据频谱数据反推电话号码 255
15.5 离散傅里叶逆变换 256
15.5.1 快速傅里叶逆变换的推导 256
15.5.2 快速傅里叶逆变换的算法实现 257
15.6 利用傅里叶变换实现频域均衡器 257
15.6.1 频域均衡器的实现原理 258
15.6.2 频域信号的增益与衰减 258
15.6.3 均衡器的实现——仿 Foobar的18段均衡器 260
15.7 总结 261
15.8 参考资料 262
第 16章 全局最优解与遗传算法 263
16.1 遗传算法的原理 263
16.1.1 遗传算法的基本概念 264
16.1.2 遗传算法的处理流程 265
16.2 遗传算法求解0-1背包问题 270
16.2.1 基因编码和种群初始化 270
16.2.2 适应度函数 271
16.2.3 选择算子设计与轮盘赌算法 272
16.2.4 交叉算子设计 273
16.2.5 变异算子设计 274
16.2.6 这就是遗传算法 275
16.3 总结 276
16.4 参考资料 276
第 17章 计算器程序与大整数计算 277
17.1 哦,溢出了,出洋相的计算器程序 277
17.2 大整数计算的原理 278
17.2.1 大整数加法 279
17.2.2 大整数减法 281
17.2.3 大整数乘法 283
17.2.4 大整数除法与模 284
17.2.5 大整数乘方运算 286
17.3 大整数类的使用 287
17.3.1 与 Windows的计算器程序一决高下 287
17.3.2 最大公约数和最小公倍数 287
17.3.3 用扩展欧几里得算法求模的逆元 290
17.4 总结 292
17.5 参考资料 292
第 18章 RSA算法——加密与签名 293
18.1 RSA 算法的开胃菜 293
18.1.1 将模幂运算转化为模乘运算 294
18.1.2 模乘运算与蒙哥马利算法 295
18.1.3 模幂算法 296
18.1.4 素数检验与米勒 拉宾算法 296
18.2 RSA算法原理 299
18.2.1 RSA算法的数学理论 300
18.2.2 加密和解密算法 300
18.2.3 RSA 算法的安全性 301
18.3 数据块分组加密 302
18.3.1 字节流与大整数的转换 302
18.3.2 PCKS与OAEP加密填充模式 303
18.3.3 数据加密算法实现 305
18.3.4 数据解密算法实现 305
18.4 RSA 签名与身份验证 306
18.4.1 RSASSA-PKCS与RSASSA-PSS签名填充模式 307
18.4.2 签名算法实现 309
18.4.3 验证签名算法实现 309
18.5 总结 310
18.6 参考资料 311
第 19章 数独游戏 312
19.1 数独游戏的规则与技巧 312
19.1.1 数独游戏的规则 312
19.1.2 数独游戏的常用技巧 313
19.2 计算机求解数独问题 314
19.2.1 建立问题的数学模型 315
19.2.2 算法实现 316
19.2.3 与传统穷举方法的结果对比 318
19.3 关于数独的趣味话题 318
19.3.1 数独游戏有多少终盘 318
19.3.2 史上最难的数独游戏 319
19.4 总结 320
19.5 参考资料 320
第 20章 华容道游戏 321
20.1 华容道游戏介绍 321
20.2 自动求解的算法原理 322
20.2.1 定义棋盘的局面 323
20.2.2 算法思路 324
20.3 自动求解的算法实现 326
20.3.1 棋局状态与Zobrist哈希算法 326
20.3.2 重复棋局和左右镜像的处理 329
20.3.3 正确结果的判断条件 330
20.3.4 武将棋子的移动 331
20.3.5 棋局的搜索算法 333
20.4 总结 335
20.5 参考资料 335
第 21章 A*寻径算法 336
21.1 寻径算法演示程序 336
21.2 Dijkstra算法 338
21.2.1 Dijkstra算法原理 338
21.2.2 Dijkstra算法实现 338
21.2.3 Dijkstra算法演示程序 339
21.3 带启发的搜索算法——A*算法 341
21.3.1 A*算法原理 342
21.3.2 常用的距离评估函数 343
21.3.3 A*算法实现 346
21.4 总结 348
21.5 参考资料 348
第 22章 俄罗斯方块游戏 349
22.1 俄罗斯方块游戏规则 350
22.2 俄罗斯方块游戏人工智能的算法原理 351
22.2.1 影响评价结果的因素 351
22.2.2 常用的俄罗斯方块游戏人工智能算法 352
22.2.3 Pierre Dellacherie算法 353
22.3 Pierre Dellacherie算法实现 355
22.3.1 基本数学模型和数据结构定义 356
22.3.2 算法实现 358
22.4 总结 364
22.5 参考资料 365
第 23章 博弈树与棋类游戏 366
23.1 棋类游戏的 AI 366
23.1.1 博弈与博弈树 367
23.1.2 极大极小值算法 368
23.1.3 负极大值算法 369
23.1.4 “α-β”剪枝算法 370
23.1.5 估值函数 372
23.1.6 置换表与哈希函数 373
23.1.7 开局库与终局库 375
23.2 井字棋——最简单的博弈游戏 376
23.2.1 棋盘与棋子的数学模型 376
23.2.2 估值函数与估值算法 377
23.2.3 如何产生走法(落子方法) 379
23.3 奥赛罗棋(黑白棋) 380
23.3.1 棋盘与棋子的数学模型 382
23.3.2 估值函数与估值算法 385
23.3.3 搜索算法实现 388
23.3.4 最终结果 392
23.4 五子棋 392
23.4.1 棋盘与棋子的数学模型 394
23.4.2 估值函数与估值算法 395
23.4.3 搜索算法实现 399
23.4.4 最终结果 400
23.5 总结 401
23.6 参考资料 401
第 24章 KNN算法与手写数字识别 403
24.1 KNN算法原理 403
24.1.1 算法工作原理 404
24.1.2 来个例子,增加点感性认识 405
24.2 手写数字识别程序设计 406
24.2.1 数字文件的格式 406
24.2.2 样本和数据集的处理 408
24.2.3 训练和测试数据 410
24.3 总结 411
24.4 参考资料 411
第 25章 有趣的变声器 412
25.1 声调的变化 412
25.2 声调变化的算法实现 413
25.2.1 回顾DFT 413
25.2.2 改变声调的原理 414
25.2.3 理解Stephan M. Bernsee算法实现 417
25.3 声调变化的算法改进 421
25.3.1 支持多声道音频数据 421
25.3.2 算法效率改进 422
25.4 参考资料 422