View on GitHub

ITMO-PE

My study notes about Program Engineering at University ITMO

MainPage/Discrete Mathematics/Discrete Mathematics

离散数学

第一章 基础:逻辑和证明

§1.1 命题逻辑

§1.2 命题逻辑的应用

§1.3 命题等价式

§1.4 谓词和量词

§1.5 嵌套量词

§1.6 推理规则

§1.7 证明导论

§1.8 证明的方法和策略

第二章 基本结构:集合、函数、序列、求和和矩阵

§2.1 集合

林鹏版

Tolia 版

§2.2 集合运算

§2.3 函数

§2.4 序列与求和

集合的基数

矩阵

第3章 算法

3.1算法

3.1.1引言

定义 1 算法是进行一项计算或解决一个问题的准确指令的有限序列。

算法的性质算法一般都共有一些性质。当描述算法时牢记这些性质是有益的。这些性质是:

3.1.2搜索算法

线性搜索 算法称为线性搜索或顺序搜索算法。线性搜索算法从比较 x 和 $a_1$ 开始。如果 $x = a_1$,那么解就是 $a_1$ 的位置,即 1。当 $x \neq a_1$ 时,比较 x 和 $a_2$。如果 $x = a_2$,解就是 $a_2$ 的位置,即 2。当 $x \neq a_2$ 时,比较 x 与 $a_3$。继续这一过程,逐一比较 $x$ 和表中的每一项直到找到匹配为止,这里解就是该项的位置除非没有匹配。如果已搜索了整个表却不能定位 x,那么解是 0。

二分搜索 当表中各项以升序出现时可以用这一算法(例如,如果项为数值,则按从最小到最大顺序排列;如果是单词,则可以按字典序或字母序排列)。这个算法称为二分搜索算法。它是通过比较要搜索的元素与表的中间项进行的。然后此表就分成两个较小的长度相等的子表,或其中较短的列表比另一个少一项。根据与中间项的比较结果, 可以将搜索局限于一个合适的子表继续进行。

3.1.3排序

假定有一个集合元素的列表。再假设有一种方式可以给集合的元素排序。排序(sorting)就是把这些元素排成一个列表,其中元素按照升序排列。

冒泡排序 冒泡排序(bubblesort)是最简单的,但不是最有效的排序算法之一。冒泡排序通过连续比较相邻的元素,如果相邻元素顺序不对就交换相邻元素,从而把一个表排列成升序。 为了实现冒泡排序,我们执行基本操作,即交换一个较大元素与紧跟其后的较小元素,从表头开始完整地执行一遍。迭代这个过程直到排序完成。

插入排序 插入排序(insert sort)是一种简单的排序算法,但通常不是最有效的。为了给 n 个元素的表排序,插入排序从第二个元素开始。插入排序将这第二个元素与第一个元素比较:如果它不大于第一个元素,就把它插入到第一个元素前面;如果它大于第一个元素,就把它插入到第一个元素后面。此时前两个元素顺序正确。然后第三个元素与第一个元素比较,如果它大于第一个元素,再与第二个元素比较;它将插入到前三个元素中的正确位置上。

3.1.4贪婪算法

一种最简单的方法常常能导致最优化问题的一个解。这种方法在每一步都选择最好的选项,而不是通盘考虑可能导致最优解的全部步骤序列。在每一步都选择看起来“最好的”选项的算法称为贪婪算法(greedyalgorithm)。一旦贪婪算法求出了一个可行解,就要确定它是否找到了一个最优解。为此,要么证明这个解是最优的,要么证明该算法产生了一个非最优解的反例。

3.1.5停机问题

停机问题 (halting problem) 它询问是否存在一个过程(procedure)能做这件事:该过程以一个计算机程序以及该程序的一个输入作为输入,并判断该程序在给定输入运行时是否最终能停止。显然,如果真的存在,有这样一个过程是非常方便的。在编写或者调试程序的时候,能够判断一个程序是否进入无限循环是非常有帮助的。然而,1936年图灵证明这样的过程是不存在的。

3.2函数的增长

3.2.2大O记号

定义 1 令 f 和 g 为从整数集或实数集到实数集的函数。如果存在常数 C 和 k 使得只要当 $x > k$ 时就有 \(\lvert f(x) \rvert \le C\lvert g(x)\rvert\) 我们就说 $f(x)$ 是 $O(g(x))$ 的。这个可以读作 $f(x) 是大 Og(x)的$ 评注 直觉上,$f(x)$ 是 $O(g(x))$ 的定义是说当 x 无限增长时,$f(x)$ 的增长慢于 $g(x)$ 的某个固定的倍数。

大 O 记号定义中的常数 C 和 k 称为 f(x) 是 O(g(x)) 的关系的凭证(witness)。为了建立 f(x) 是 O(g(x)),我们只需要这一关系的一对凭证。即要证明 f(x) 是 O(g(x)) 的,我们需要找出一对常数 C 和 k,即凭证,使得只要当 $x > k$ 时就有 $\lvert f(x) \rvert \le C\lvert g(x) \rvert$。

注意当有 $f(x)$ 是 $O(g(x))$ 的关系的一对凭证时,就会有无限多对凭证。要明白这一点,注意如果 C 和 k 是一对凭证,那么任意一对 C’ 和 k’(其中 $C < C’$ 和 $k < k’$ 也是一对凭证,因为只要当 $x > k’ > k$ 时就有 $\lvert f(x) \rvert \le C\lvert g(x) \rvert \le C’ \lvert g(x) \rvert$。 评注 f(x)是 O(g(x)) 的事实有时写作 f(x) = O(g(x))。不过这一写法中的等号并不代表真正的相等,而是告诉我们对于这些函数定义域中足够大的数而言,函数 f 和 g 的值之间有不等式成立。然而,$f(x) \in O(g(x))$ 这样的写法也是可接受的,因为 $O(g(x))$ 可以表示那些是 $O(g(x))$ 函数的集合。

3.2.3一些重要函数的大O估算

定理 1 令 $f(x) = a_n^n + a_{n-1}x^{n-1} + \cdots + a_1x +a_0$,其中 $a_0, a_1, \cdots, a_{n-1},a_n$ 为实数。那么 f(x) 是 $O(x^n)$ 的。

3.2.4函数组合的增长

定理 2 假定 $f_1(x)$ 是 $O(g_1(x))$ 的,$f_2(x)$ 是 $O(g_2(x))$ 的,那么 $(f_1+f_2)(x)$ 是 $O(max\lvert g_1(x)\rvert, \lvert g_2(x)\rvert))$ 的。 推论 1 假定 $f_1(x)$ 和 $f_2(x)$ 都是 $O(g(x))$ 的,那么 $(f_1+f_2)(x)$ 也是 $O(g(x))$ 的。

定理 3 假定 $f_1(x)$ 是 $O(g_1(x))$ 的,$f_2(x)$ 是 $O(g_2(x))$ 的。那么 $(f_1f_2)(x)$ 是 $O(g_1(x)g_2(x))$ 的。

3.2.5大 $\Omega$ 与大 $\Theta$ 记号

大 O 记号广泛用于描述函数的增长,但它也有局限性。特别是,当 f(x) 是 O(g(x)) 时,我们只有用 g(x) 来估计对于大 x 值的 f(x) 大小的一个上限。可是,大 O 记号不能提供对大 x 值的 f(x) 大小的一个下限。为此,我们使用大 $\Omega$ 记号。当希望给出函数 f(x) 的相对于参照函数 g(x) 的上限和下限时,我们使用大 $\Theta$ 符号。

定义 2 令 f 和 g 为从整数集合或实数集合到实数集合的函数。如果存在正常数 C 和 k 使得当 x>k 时有 \(\lvert f(x) \rvert \ge C\lvert g(x) \rvert\) 我们说 f(x) 是 $\Omega(g(x))$ 的,这个读作 $f(x) 是大 \Omega g(x) 的$。

定义 3 令 f 和 g 为从整数集合或实数集合到实数集合的函数。如果 f(x) 是 $\Theta(g(x))$ 的且 $f(x)$ 是 $\Omega(g(x))$ 的,我们就说 f(x) 是 $\Omega(g(x))$ 的。当 $f(x)$ 是 $\Theta (g(x))$ 时就说 f(x) 是大西塔 g(x)的,即 f(x) 是 g(x) 阶的,或 f(x) 和 g(x) 是同阶的。

定理 4 令 $f(x) = a_n^n + a_{n-1}x^{n-1} + \cdots + a_1x +a_0$,其中 $a_0, a_1, \cdots, a_{n-1},a_n$ 为实数且 $a_n \neq 0$。那么 f(x) 是 $x^n$ 阶的。

3.3算法的复杂度

3.3.5理解算法的复杂度