孙猛 http://www.math.pku.edu.cn/teachers/sunm 2017 年 9 月 14 日
课程内容 : 基本 一致 ( 教学 大纲 ) 但本课程这学期会根据进度选择介绍 一些教材之外的内容 ( 插值查找 表排序 高维结构等 ) Project: 难度和数 目都会更更 高!!! 需要花更更多的时间去读 文献和做 Presentation 2
教材 张乃孝 陈光 孙猛 算法与数据 结构 C语 言描述 第3版 高 等教育出版社 2011 张乃孝编著 算法与数据结构 (第2 版)学习指导与习题解析 高等教育 出版社 2009 更更多参考 文献 见课程主 页 to be provided soon 3
上课时间地点 : 周 一5-6 节 ( 双周 ), 周四 3-4 节 ( 每周 ), 二教 422 上机信息 : 每周 二11-12 节 ( 第三周开始 ), 计算中 心4 号机房 账号 :shy2-1112, 密码 data2017 期末考试 : 2018.1.4 上午, 闭卷考试 4
Office Hour: 周四下午 2:00-3:00 pm, 需提前 email 预约 答疑之前, 先 Google 你的问题看是否有 人在 网上问过 作业有关的问题请联系助教, 不不要让我给你调代码 助教 : 李李屹 (liyi_math@pku.edu.cn) 张喜悦 (xiyuezhang4869@163.com) 5
成绩由以下部分组成 : 1. Project,3 次, 共计 40%(10+10+20) 第 1 2 次独 立完成, 作业成绩程序与论 文各占 50% 第 3 次 3-4 人 一组协作完成, 并在课上报告,Project 成绩 程序 论 文与报告分别占 40% 40% 20% 每次项 目程序和论 文均需按时提交 2. 平时 小作业,n 次, 共计 10%, 独 立完成, 按时提交 3. 期末考试,50%, 闭卷考试 考试 : 概念等 一般性问题 ( 判断 / 选择 / 填空 / 简答 / 作图 / 比较 / 分析 / 设计 / 讨论等 ) 算法设计与分析 程序实现 6
作业通过教学 网提交, 不不要直接发 email 给任课教师 或助教 作业可以延期提交, 最多延期 1 周, 延期提交者该次 成绩按 50% 计算, 超过 1 周之后该次作业提交系统将 关闭, 之后系统不不再接受任何该次作业提交 7
北北京 大学本科考试 工作与学术规范条例例第四章第 十九条 : 学 生对考试成绩有异议, 可以申请核查试卷 学 生申请查卷, 须在下 一学期开学 2 周内, 持学 生证向开课院 ( 系 所 中 心 ) 教务办公室提出书 面申请, 经主管教学领导批准, 由任课教师和教务员在教务办公室核查试卷 ; 超过规定期限或 非本校课程的考试, 不不受理理查卷 8
Best 15 Graduate Degrees with Median Salary from FORTUNE.com in 2016 Master of Biostatistics ($105,900) Master of Statistics ($113,700) Ph.D. of Computer Science ($147,400) Ph.D. of Economics ($125,800) Master of Applied Math ($124,900) Master of Computer Science ($125,700) Ph.D. of Pharmacy ($126,000) Ph.D. of Math ($106,600) Ph.D. of Physics ($137,800) Master of Software Engineering ($118,900) Ph.D. of Physical Chemistry ($134,800) Master of Information Systems ($116,100) Master of Physician Assistant Studies ($103,600) MBA of Management Information Systems ($117,800) Ph.D of Political Science ($116,700) 9
10
我觉得应该学的知识 学到的知识 能够帮助赚钱的知识 数据结构和算法 11
12
用计算机解决实际问题, 就是要在计算机中建 立 一个 解决这个问题的模型 程序是使 用程序设计语 言精确描述的实际问题求解的 模型 程序中描述的数据 用来表示问题中涉及的对象, 程序中描述的函数 ( 过程 ) 表示了了对于数据的处理理算法 ; 通过接受实际问题的输 入, 经过程序的运 行行, 便便可以得到实际问题的 一个解 13
现实世界 计算机世界 需求模型 数学模型 程序 分析设计编程 数据结构 + 算法 调试和维护 14
为 一个多叉路路 口设计信号灯管理理系统 对可能 行行驶路路线实 行行分组 : 组内各 方向 行行驶 无冲突 ( 可 行行 ) 组数尽可能少 ( 有效 最优解 ) 15
可以确定 13 个可能通 行行 方向 : A B,A C,A D, B A,B C,B D, D A,D B,D C, E A, E B, E C, E D 16
17
把上图中的 一个结点理理解为 一个国家, 结点之间的连线看作两国有共同边界, 上述问题就变成著名的 着 色问题 : 即求出 ( 最少 ) 要 几种颜 色可将 一个地图中所有国家着 色, 使得任意两个相邻的国家颜 色都不不相同 18
具体做法 : 从分为 1 2 3 组开始考察, 逐个列列举出所有可能的着 色 方案, 检查这样的分组 方案是否满 足要求 首先满 足要求的分组, 自然是问题的最优解 这类穷举法对结点少的问题 ( 称为 规模 小的 问题 ) 还 可以 用 ; 对规模 大的问题, 由于求解时间会随着实际 问题规模的增 长 而指数性上升, 使计算机 无法承受 19
先 用 一种颜 色给尽可能多的结点上 色 ; 然后 用另 一种颜 色在未着 色结点中给尽可能多的结点上 色 ; 如此反复直到所有结点都着 色为 止 绿 色 :AB AC AD BA DC ED 蓝 色 :BC BD EA 红 色 :DA DB 白 色 :EB EC AB AC AD BA BC BD DA D B DC EA EB EC ED 20
使 用国名表示国家 ; 国名的集合表示国家的分组 使 用 一个图表示地图 图中的结点名表示对应的国家 ; 图中的边表示联系的两个国家有公共边界 需要着 色的图是 G,G 中所有结点的集合记为 G.V 集合 V1 存放图中所有未被着 色的结点 集合 NEW 存放可以 用某颜 色着 色的所有结点 21
判断元素 v 是否属于集合 V1: v V1; 从集合 V1 中去掉 一个元素 v: remove(v1, v); 向集合 NEW 里里增加 一个元素 v: add(new, v); 判断集合 V1 是否空集合 :isempty(v1); 检查结点 v 与结点集合 NEW 中各结点之间在图 G 中是否有边连 接 : notadjacentwith (NEW, v, G) 22
从 V1 中找出可 用新颜 色着 色的结点集的 工作可以 用下 面的伪码 描述 : 置 NEW 为空集合 ; for 每个 v V1 do if v 与 NEW 中所有结点间都没有边 从 V1 中去掉 v ; 将 v 加 入 NEW ; 这个伪码如果能执 行行, 集合 NEW 中就得到 一组可以 用新颜 色着 色的结点 着 色程序可以反复调 用这段伪码, 直到 V1 为空, 每次调 用选择 一种新颜 色, 这段伪码执 行行的次数就是需要的不不同颜 色个数 23
int colorup(graph G) { int color = 0; // 记录使 用的颜 色数 set V1 = G.V; //V1 初始化为图 G 的结点集 V set NEW; while(!isempty(v1)) { NEW = { }; while (v V1. notadjacentwith(new, v, G)) { add(new,v); remove(v1,v); } ++color; } return color; // 返回使 用的颜 色数 } 24
如果集合和图是程序设计语 言中预定义的类型, 则 colorup 中 用到的 remove(v1, v) 和 add(new, v) 等就应该是语 言中预定义的内部函数, 该程序就 几乎可以直接上机运 行行 否则程序员需要 自 己 用语 言所提供的 ( 类型 ) 机制实现这些抽象数据类型 ( 集合 图等 ) 很多语 言没有这类 高级结构, 只有 一些基本数据类型 这时就需要 自 己实现集合 图及其相应操作 如何有效实现这类 高级结构就是数据结构研究的问题 25
在数据结构确定以后, 算法的描述可以进 一步根据设计的数据 结构进 行行精化 如果在这个过程中 又出现 比较复杂的问题需要解决 ( 例例如 : 如何检查结点 v 与结点集合 NEW 中各结点之间在图 G 中是否有边连接问题 ), 就可能还需要重复前 面的思路路构思求解 方法, 选择必要的抽象数据类型并 用适当的数据结构和算法实现它们 经过这种反复的精化过程, 最后将算法中所有部分都细化为能 用程序设计语 言描述的成分, 得到的就是我们希望的程序 26
类型 一组值 ( 或者对象 ) 的集合 数据类型 在计算机 ( 语 言 ) 中可以使 用的 一个类型, 它不不但包 括这个类型的值的集合, 还包括定义在这个类型上 的 一组操作 27
有 一定 行行为 ( 操作 ) 的抽象 ( 数学 ) 类型 抽象出数据类型的使 用要求, 而把它的具体表示 方式和运算的实现细节都隐藏起来 支持数据类型的实现与使 用分离的原则, 是 一种 十分有效的对问题进 行行抽象与分解的思维 工具 允许独 立地考虑数据类型的外部接 口和内部的实现 对于系统的分解 设计 维护和修改 十分有利利, 是 面向对象技术与 方法的主要理理论基础 28
ADT Circle is data real r; real x, y; operations real area ( ) real circumference( ) real getradius ( )...... end ADT Circle; 29
C 没有为 ADT 提供专 门 支持 (C 语 言设计时还没认识到 ADT 的重要性 ), 但可通过程序技术模拟 在 C 里里实现 一个 ADT 通常 用两个 文件,.h 文件定义数据表示 ( 定义类型 ) 和操作原型,.c 文件实现操作 以 Circle 为例例,circle.h 文件 : typedef struct { double x, y, r; } Circle; Circle createcircle (double x, double y, double r); double area (Circle c); double circumference (Circle c);...... /* 其他操作的声明 ( 原型 )*/ 30
circle.c 文件 : #include "circle.h" const double pi = 3.14159265; circle createcircle (double x, double y, double r) { Circle c; c.x = x; c.y = y; c.r = r; return c; } double area (Circle c) { return c.r *c.r *pi; } double circumference (Circle c) { return 2 * c.r * pi; }...... /* 其他操作的实现 */ 使 用 Circle 类型的 文件应 #include "circle.h", 做可执 行行程序时应把 文件 circle.c 作为其中 一部分 31
传统的概念 : 数据结构是计算机中表示 ( 存储 ) 的 具有 一定逻辑关系和 行行为特征的 一组数据 根据 面向对象的观点 : 数据结构是抽象数据类 型的物理理实现 主要解决两个问题 : 如何具体表示抽象数据类型中的数学模型 ; 如何给出抽象数据类型中需要操作的实现 32
逻辑结构 ( 数学模型 ) 指数学模型 ( 集合, 表, 树和图等 ) 中的基本元素 ( 结点 ) 之间的相互关系 ( 在抽象数据类型中这些关系隐含在数学名称中 ) 描述 方式 :B=<K, R>, K 是结点的有穷集合,R 是 K 上的 一个关系 存储结构 ( 物理理结构 ) 指数学模型的具体表示 方式, 包括结点的表示和关系的表示 数据的逻辑结构在计算机存储器器中的映射 ( 或表示 ) 操作 ( 行行为 ) 指抽象数据类型关 心的各种 行行为在不不同的存储结构上的具体实现 ( 算 法或程序 ) 33
按逻辑结构分类 给定 B = <K,R>, 若 <k1, k2> R, 则称 k1 为 k2 的前驱,k2 为 k1 的后继 没有前驱的结点为开始结点, 没有后继的结点为终端结点 根据 R 的特点可以将数据结构分为以下三类 : 线性结构 : K 中每个结点最多只有 一个前驱和 一个后继 树形结构 : K 中每个结点最多只有 一个前驱, 但可有多个后继 复杂结构 :K 中结点的前驱 后继结点的个数都不不作限制 特别地 集合结构 : 当 R 为空集时,K 中结点间没有约束关系 34
按存储结构分类 计算机的内存提供了了 一个可以连续存储 随即存取和连续编址的存储空间 存储结构的设计 目标, 就是使 用 比较少的空间记录逻辑结构的必要信息, 并且有效实现抽象数据类型中要求的操作 四种最基本的存储 方法 顺序表示 链接表示 散列列表示 索引表示 35
顺序表示 用 一个连续的空间, 顺序存放数据结构中的各个结点 适合表示线性结构 : 结点之间的逻辑关系可以 用存储空间的物理理次序来反映 顺序存储法为使 用整数编码来访问数据结点提供了了便便利利 36
链接表示 结点的存放位置是任意的, 结点之间的关系通过与结点关联的链接 ( 指针 引 用等 ) 方式显式地表达出来 比较灵活, 适合表示经常进 行行插 入 删除等动态变化的数据结构 37
散列列表示 : 关键码 - 地址转换法 选择适当的散列列 ( 杂凑 ) 函数, 根据关键码的值将结点映射到给定的存储空间 ( 散列列表 ) 中 检索的效率近似随机存取, 适合于要 高速检索的结构 索引表示 给出 一种从关键码到存储地址的映射 方法, 即建 立辅助的索引结构 每个索引项包含 一个结点的关键码和该结点的存储位置 38
按操作 ( 行行为 ) 分类 行行为的规范由抽象数据类型决定队列列 先进先出栈 后进先出 行行为的实现由算法决定但与存储表示关系密切集合元素的排序算法 顺序表示 链接表示 39
算法是由有穷规则构成 ( 为解决某 一类问题 ) 的运算序列列 算法可以有若 干输 入 ( 初始值或条件 ); 算法通常 又有若 干个输出 ( 计算结果 ) 算法应该具有有穷性 一个算法必须在执 行行了了有穷步之后结束 算法应该具有确定性 算法的每 一步, 必须有确切的定义 算法应该具有可 行行性 算法中的每个动作, 原则上都是能够由机 器器或 人准确完成的 40
如果 一个算法以 一组满 足初始条件的输 入开始, 那么 该算法的执 行行 一定终 止, 并且在终 止时得到满 足要求 的 ( 输出 ) 结果 41
程序就是在数据的某些 特定的结构和表示的基 础上对于算法的描述 算法与数据结构是程序 设计中相辅相成 不不可 分割的两个 方 面 42
贪 心法 分治法 回溯法 动态规划法 分 支限界法 43
当追求的 目标是 一个问题的最优解时, 设法把对整个问题的求解 工作分成若 干步骤来完成 在其中的每 一个阶段都选择从局部看是最优的 方案, 以期望通过各阶段的局部最优选择达到整体的最优 贪 心法实际上不不能保证都成功地产 生 一个全局性最优解, 但是通常可以得到 一个可 行行的较优解 44
把 一个规模较 大的问题分成两个或多个较 小的与原问题相似的 子问题 首先对 子问题进 行行求解, 然后设法把 子问题的解合并起来, 得出整个问题的解, 即对问题分 而治之 如果 一个 子问题的规模仍然 比较 大, 不不能很容易易地求得解, 就可以对这个 子问题重复地应 用分治策略略 45
有 一些问题, 需要通过彻底搜索所有可能情况寻找 一个满 足某些预定条件的最优解 由于彻底搜索的运算量量通常 非常 大, 所以采取 一步 一步向前试探, 当有多种选择时可以任意选择 一种, 只要 目前可 行行就继续向前, 一旦发现问题或失败就后退, 回到上 一步重新选择, 借助于回溯技巧和中间增加判断, 这样常常可以 大 大地减少搜索时间 常 见的迷宫问题以及 八皇后问题都可以 用回溯 方法来 解决 46
与分治法相似都是把 一个 大问题分解为若 干较 小的 子问题, 通过求解 子问题 而得到原问题的解 不不同点是 : 分治法每次分解的 子问题数 目 比较少, 子问题之间界限清楚, 处理理 的过程通常是 自顶向下进 行行 ; 动态规划法分解的 子问题可能 比较多, 而且 子问题相互包含, 为了了重 用已经计算的结果, 要把计算的中间结果全部保存起来, 通常是 自底向上进 行行 在带权图中, 求所有结点之间最短路路径的 Floyd 算法就属于动态规划法 47
与回溯法相似, 也是 一种在表示问题解空间的树上进 行行系统搜索的 方法 所不不同的是, 回溯法使 用了了深度优先策略略, 而分枝限界法 一般采 用 广度优先策略略或者采 用最 大收益 ( 或最 小损耗 ) 策略略, 并且利利 用最优解属性的的上下界来控制搜索的分枝 教材最后 一章, 在讨论背包问题时, 介绍了了 一个 用分枝限界法设计的算法 48
算法不不仅要正确, 而且要有效 算法分析就是度量量算法性质的过程 : 分析 一个算法主要是看这个算法的执 行行需要花费多少机器器资 源 最常 用的算法度量量特性 : 空间代价 ( 空间复杂性 ): 被解决问题的规模 ( 以某种单位计 ) 为 n 时, 某求解算法所需存储空间按某种单位为 S(n), 则称该算法的空间代价为 S(n) 时间代价 ( 时间复杂性 ): 当问题规模 ( 以某种单位计 ) 为 n 时, 算法所耗时间按某种单位为 T(n), 则称该算法的时间代价为 T(n) 49
问题规模 空间单位 时间单位 需要根据实际问题的情况确定 50
求解某问题的 一个具体算法, 对不不同的问题实例例, 也 可能耗费不不同的时间和空间, 全 面分析 一个算法需要 考虑 最坏情况下时间 ( 空间 ) 复杂性 平均时间 ( 空间 ) 复杂性 最好情况下时间 ( 空间 ) 复杂性 51
大 O 表示法 更更关注算法复杂性的量量级 ; 若存在正常数 c 和 n 0, 当问题的规模 n n 0 后, 某算 法的时间 ( 或空间 ) 代价 T(n) c f(n), 则说该算法的 时间 ( 或空间 ) 代价为 O(f(n)) 52
53
加法规则 ( 顺序复合 ) 算法分为两部分时, 复杂性是两部分复杂性之和 T(n) = T 1 (n)+t 2 (n) = O(f 1 (n))+o(f 2 (n)) = O(max(f 1 (n), f 2 (n))) 乘法规则 ( 循环 ) 循环 T 1 (n) 次, 每次 T 2 (n) 时间, 则 T(n) = T 1 (n) T 2 (n) = O(f 1 (n)) O(f 2 (n)) = O(f 1 (n) f 2 (n)) 54
55
理理解从问题到程序的主要过程 ; 体会抽象数据类型 数据结构和算法在问题求解过程 中的作 用 ; 了了解数据结构的主要概念和分类 ; 了了解算法的概念和主要设计 分析 方法 56
一个抽象数据类型决定了了 一组需要的操作 不不同抽象数据类型的实现, 可以选择相同的逻辑结构 对于 一种逻辑结构, 往往可以采 用不不同的存储结构 一个算法的思想可以独 立于具体的数据表示, 但是操作的实现, 总是依赖于具体的存储结构 具体选择何种存储结构, 主要应该考虑操作的要求 使得主要运算的开销, 在时间和空间的权衡中达到最佳效果 算法的时间代价是选择与评价不不同存储结构的关键 57
理理解抽象数据类型 数据结构和算法的概念 ; 掌握设计数据结构与算法的主要原理理和 方法 ; 比较不不同数据结构和算法的特点 ; 提 高使 用计算机解决问题的能 力力 58