第一章 算法引论

第一章 算法引论

1.1 引子

1.1.1排序问题

(1)问题描述:

输入: 数字序列 X = < a 1 , a 2 , . . . , a n > X= <a1, a2, ..., an> X=<a1,a2,...,an>;

输出: 一个排列 X ′ = < a ′ 1 , a ′ − , . . . , a ′ n > X'= <a'1, a'-,..., a'n> X=<a1,a,...,an>。数字序列X与X’之间为满射或一一映射(即元素―—对应),并且有 a ′ 1 ≤ a ′ 2 ≤ . . . ≤ a ′ n a'1≤ a'2≤ ...≤ a'n a1a2...an(元素间非降序)。

例如:

√输入:8,2,2,9,3,6

√输出:2,2,3,6, 8, 9

(2)排序方法:

冒泡、插入、归并、二叉树、桶排序等。稳定的;

选择、Shell、堆、快速、组合排序等。不稳定的。

1.1.2插入排序:

(1)插入排序的原理:

通过逐步构建有序序列实现排序。对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

image-20211223144619370

(1)插入排序算法的伪代码:
INSERTION-SORT (A, n)//A[1..n]
    for j = 2 to n do
        key = A[j]
        i = j - 1
        while i > 0 and A[i] > key do
            A[i+1] = A[i]
            i = i - 1
        A[i+1] = key
(3)插入排序算法的正确性证明一基于循环不变式(LoopInvariant):

循环不变式: 在每次循环迭代之前,子数组 A [ 1.. j − 1 ] A[1..j-1] A[1..j1]已包含了最初位于 A [ 1.. j − 1 ] A[1..j-1] A[1..j1]、但已排好序的各个元素。

初始化: 第一轮迭代之前(即j=2),子数组A[1…j-1](即A[1])显然保持了循环不变式;

保持: 假设第j次迭代之前循环不变式为真。该算法的第j次操作只是将A[j]与已有序的A[1…j-1]中的元素进行比较,找到合适位置并插入。j+1次迭代之前,显然A[1…(j+1)-1]也保持了循环不变式;

终止: j=n+1时,显然 A [ 1.. ( n + 1 ) − 1 ] A[1..(n+1)-1] A[1..(n+1)1](即A[1…n])已包含了最初位于A[1…n]、且已排好序的各个元素。

(4)插入排序算法的运行时间分析:

最坏情况: T ( n ) = O ( n 2 ) T(n) = O(n^2) T(n)=O(n2)。算术级数。

平均情况: T ( n ) = O ( n 2 ) T(n) = O(n^2) T(n)=O(n2)。算术级数;

最好情况: T ( n ) = O ( n ) T(n)= O(n) T(n)=O(n)。已非降序。

(5)插入排序算法的运行时间的递归方程:

{ W ( n ) = W ( n − 1 ) + n − 1 W ( 1 ) = 0 \left\{\begin{array}{l} W(n)=W(n-1)+n-1 \\ W(1)=0 \end{array}\right. {W(n)=W(n1)+n1W(1)=0

1.1.3归并排序:

(1)归并排序算法的原理:

基于分而治之思想,递归地把待排序序列分解为若干子序列并进行排序,再把已排序的子序列合并为整体有序序列,最终实现全序列的有序。

(2)归并排序算法的伪代码:
MERGE-SORT(A, low, high) //A[1..n]
    if low < high
        mid = [low + high)/ 2]
        MERGE-SORT(A, low, mid)
        MERGE-SORT(A, mid+1, high)
        MERGE(A, low,mid, high)
MERGE(A,l, m, h) //A[1..n]
    n1 = m-l+ 1//前半段长度
    n2 = h-m   //后半段长度
    let L[1..n,+1]and R[1..n2+1] be new arrays
    for i = 1 to n1 do
        L[i]= A[l+i -1]//数组赋值
    for j = 1 to n2 do
        R[i]= A[m + j]//数组赋值
	L[n + 1] = ∞
	R[n + 1] = ∞
          i= 1
          j= 1
	for k = l to h//从头到尾
          if L[i]≤R[i]
              A[k]= L[i]
              i++
          else
              A[k]= R[j]
              j++
(3)归并排序算法中的MERGE:

image-20211223151712323

(4)归并排序算法的运行时间分析(递归树或主定理)

image-20211223151900612

1.2 算法的基本概念

1.2.1算法(Algorithm):

对于计算机科学来说,算法指的是对特定问题求解步骤的一种描述,是若干条指令的有穷序列。

(1)算法的特性:

· 输入(0个或多个)

· 输出(至少1个)

· 确定性(无歧义)

· 有限性

· 可行性

(2)描述方式:

自然语言、流程图、伪代码、程序设计语言;

(3)算法与程序的区别:

程序是算法用某种程序设计语言的具体实现;

程序可以不满足算法的性质(4)。如OS。

1.2.2算法的经典问题:

排序与查找、循环赛日程表(分治法)

最长公共子序列、矩阵连乘、凸多边形最优三角剖分、加工顺序等(动态规划法)

会场安排问题、单源最短路径、哈夫曼编码、最小生成树(贪心法)

n后、最大团、图的m着色(回溯法)

0-1背包、旅行商问题、布线问题(分支限界法)

……

(1)n后问题

image-20211223153047258

在n×n格的棋盘上放置彼此不受攻击的n个皇后:

据国际象棋规则,皇后可攻击与之处在同一行或同一列或同一对角线上的棋子;

n后问题等价于:如何在n×n格的棋盘上放置n个皇后,使得任何两个皇后不放在同一行或同一列或同一斜线上。

(2)0-1背包问题

image-20211223153142501
W = { w 1 , w 2 , w 3 } P = { p 1 , p 2 , p 3 } max ⁡ ( x 1 p 1 + x 2 p 2 + x 3 p 3 ) x 1 w 1 + x 2 w 2 + x 3 w 3 ≤ C \begin{aligned} &W=\left\{w_{1}, w_{2}, w_{3}\right\} \\ &P=\left\{p_{1}, p_{2}, p_{3}\right\} \\ &\max \left(x_{1} p_{1}+x_{2} p_{2}+x_{3} p_{3}\right) \\ &x_{1} w_{1}+x_{2} w_{2}+x_{3} w_{3} \leq C \end{aligned} W={w1,w2,w3}P={p1,p2,p3}max(x1p1+x2p2+x3p3)x1w1+x2w2+x3w3C

(3)布线问题

image-20211223153259994

1.3 算法设计的一般过程

image-20211223153331127

1.4 算法(复杂性)分析

1.4.1算法复杂性:

算法复杂性(亦称算法复杂度)为算法运行时所需计算机资源的度量:

时间复杂性(影响因素包括问题规模n、输入序列I、算法本身A) : T ( n , I , A ) → T ( n ) T(n,I,A)\rightarrow T(n) T(n,I,A)T(n)

空间复杂性(影响因素包括输入输出数据IO、辅助变量V、算法本身A): S ( I O , V , A ) → S ( V ) S(IO,V,A) \rightarrow S(V) S(IO,V,A)S(V)

很显然:

​ 算法所需资源越多,算法的复杂性就越高;

​ 算法所需资源越少,算法的复杂性就越低。

(1)算法(复杂性)分析:

包括:时间复杂性分析和空间复杂性分析。

方法:事后统计和事前分析。

三种情况:最好情况、平均情况和最坏情况。

(2)算法分析的意义:

算法设计:复杂性尽可能的低;

算法选用:选择复杂性最低的算法;

算法改进:算法分析有助于算法的改进。

(3)影响算法运行时间的因素(除算法本身外):

机器;

采用的语言及编译程序;

编程能力等。

(4)算法分析无需具体时间(精确或近似):

针对同一问题不同算法的比较,相对而非绝对;

应该独立于机器及实现语言;

无论科技如何发展,其运行时间的测度应该始终成立;

关心的是大的问题规模时的运行情况。→渐近复杂性

1.4.2算法的渐近(asymptotic)复杂性态:

设算法的运行时间为T(n),如果存在T*(n),使得
lim ⁡ n → ∞ T ( n ) − T ∗ ( n ) T ( n ) = C , C  is a constant.  \lim _{n \rightarrow \infty} \frac{T(n)-T^{*}(n)}{T(n)}=\mathrm{C}, \mathrm{C} \text { is a constant. } nlimT(n)T(n)T(n)=C,C is a constant. 
就称T*(n)为算法的渐近性态或渐近时间复杂性。

(1)算法的渐近复杂性态示例:

假设算法A的运行时间表达式为T1(n):
T 1 ( n ) = 30 n 4 + 20 n 3 + 40 n 2 + 46 n + 100 T ∗ 1 ( n ) ≈ n 4  (阶)  \begin{aligned} &T_{1}(n)=30 n^{4}+20 n^{3}+40 n^{2}+46 n+100 \\ &T^{*}{ }_{1}(n) \approx n^{4} \quad \text { (阶) } \end{aligned} T1(n)=30n4+20n3+40n2+46n+100T1(n)n4 (
假设算法B的运行时间表达式为T2(n):
T 2 ( n ) = 1000 n 3 + 50 n 2 + 78 n + 10   T ∗ 2 ( n ) ≈ n 3  (阶)  \begin{aligned} &\mathrm{T}_{2}(\mathrm{n})=1000 \mathrm{n}^{3}+50 \mathrm{n}^{2}+78 \mathrm{n}+10 \\ &\mathrm{~T}^{*}{ }_{2}(\mathrm{n}) \approx \mathrm{n}^{3} \text { (阶) } \end{aligned} T2(n)=1000n3+50n2+78n+10 T2(n)n3 (

1.4.3渐近意义下的记号:

 渐近上界 - O (big oh)   渐近下界 -  Ω  (big omega)   渐近紧确 (tight) 界 - の或  θ  (theta)   O (small oh) 和  ω  (small omega)  \begin{aligned} &\text { 渐近上界 - O (big oh) } \\ &\text { 渐近下界 - } \Omega \text { (big omega) } \\ &\text { 渐近紧确 (tight) 界 - の或 } \boldsymbol{\theta} \text { (theta) } \\ &\text { O (small oh) 和 } \boldsymbol{\omega} \text { (small omega) } \end{aligned}  渐近上界 - O (big oh)  渐近下界 - Ω (big omega)  渐近紧确 (tight)  - の或 θ (theta)  O (small oh)  ω (small omega) 

(1)渐近上界-O(big oh):

设f(n)和g(n)是定义在正数集上的正函数,下同。

定义:如存在正的常数c和自然数n,使得当n≥n0时有f(n)≤cg(n),则称函数f(n)当n充分大时上有界,且g(n)是它的一个上界,记为f(n)=O(g(n))。

即f(n)的阶不高于g(n)的阶。

求T(n)= 10n +4的渐近上界O:

T ( n ) = O ( n ) 或 T ( n ) = O ( n 2 ) T(n) = O(n)或T(n) = O(n^2) T(n)=O(n)T(n)=O(n2)

① 渐近上界O运算规则:

根据О的定义,容易证明它有如下运算规则:

(1) O ( f ) + O ( g ) = O ( max ⁡ ( f , g ) ) \mathrm{O}(\mathrm{f})+\mathrm{O}(\mathrm{g})=\mathrm{O}(\max (\mathrm{f}, \mathrm{g})) O(f)+O(g)=O(max(f,g));

(2) O ( f ) + O ( g ) = O ( f + g ) \mathrm{O}(\mathrm{f})+\mathrm{O}(\mathrm{g})=\mathrm{O}(\mathrm{f}+\mathrm{g}) O(f)+O(g)=O(f+g);

(3) O ( f ) O ( g ) = O ( f g ) \mathrm{O}(\mathrm{f}) \mathrm{O}(\mathrm{g})=\mathrm{O}(\mathrm{fg}) O(f)O(g)=O(fg);

(4) 如 g ( n ) = O ( f ( n ) ) g(n)=O(f(n)) g(n)=O(f(n)), 则 O ( f ) + O ( g ) = O ( f ) O(f)+O(g)=O(f) O(f)+O(g)=O(f);

(5) O ( c f ( n ) ) = O ( f ( n ) ) \mathrm{O}(\mathrm{cf}(\mathrm{n}))=\mathrm{O}(\mathrm{f}(\mathrm{n})) O(cf(n))=O(f(n)), 其中 C \mathrm{C} C 是一个正的常数;

(6) f = O ( f ) f=O(f) f=O(f)

② 常见的几类算法复杂性:

O ( 1 ) \mathrm{O}(1) O(1) : 常数阶;

O ( log ⁡ 2 n ) , O ( n log ⁡ 2 n ) \mathrm{O}\left(\log _{2} \mathrm{n}\right), \mathrm{O}\left(\mathrm{n} \log _{2} \mathrm{n}\right) O(log2n),O(nlog2n) : 对数阶;

O ( n ) , O ( n 2 ) , O ( n 3 ) , … , O ( n m ) \mathrm{O}(\mathrm{n}), \mathrm{O}\left(\mathrm{n}^{2}\right), \mathrm{O}\left(\mathrm{n}^{3}\right), \ldots, \mathrm{O}\left(\mathrm{n}^{\mathrm{m}}\right) O(n),O(n2),O(n3),,O(nm) :多项式阶。多项式时间算法;

O ( 2 n ) , O ( n ! ) , O ( n n ) \mathrm{O}\left(2^{\mathrm{n}}\right), \mathrm{O}(\mathrm{n} !), \mathrm{O}\left(\mathrm{n}^{\mathrm{n}}\right) O(2n),O(n!),O(nn) :指数阶。指数时间算法。

③ 几类复杂性之间的关系:

O ( 1 ) < O ( log ⁡ 2 n ) < O ( n ) < O ( n log ⁡ 2 n ) < O ( n ) < O ( n 2 ) < O ( n 3 ) < … < O ( n m ) < O ( 2 n ) < O ( n ! ) < O ( n n ) \begin{gathered} \mathrm{O}(1)<\mathrm{O}\left(\log _{2} \mathrm{n}\right)<\mathrm{O}(\mathrm{n})<\mathrm{O}\left(\mathrm{n} \log _{2} \mathrm{n}\right)<\mathrm{O}(\mathrm{n})<\mathrm{O}\left(\mathrm{n}^{2}\right)< \\ \mathrm{O}\left(\mathrm{n}^{3}\right)<\ldots<\mathrm{O}\left(\mathrm{n}^{\mathrm{m}}\right)<\mathrm{O}\left(2^{\mathrm{n}}\right)<\mathrm{O}(\mathrm{n} !)<\mathrm{O}\left(\mathrm{n}^{\mathrm{n}}\right) \end{gathered} O(1)<O(log2n)<O(n)<O(nlog2n)<O(n)<O(n2)<O(n3)<<O(nm)<O(2n)<O(n!)<O(nn)

(2)渐近下界-Q(big omega):

如果存在正的常数c和自然数no,使得当n > n时有f(n) ≥ cg(n),称函数f(n)当n充分大时下有界,且g(n)是其一个下界,记为f(n) =
Q(g(n))。即f(n)的阶不低于g(n)的阶。

(3)渐近紧确界–(big theta) :

如存在正的常数c1,C-和自然数n,使得当n ≥no时,有cig(n) s f(n) ≤ c2g(n),则称函数f(n)当n充分大时有紧确界,亦即g(n)和f(n)同阶。

(4)非递归算法:
① 非递归算法的时间复杂度估算:

顺序语句:各语句计算时间相加。

选择语句:条件判定语句以及各分支中语句的计算时间的较大者。

循环语句:循环体内计算时间循环次数,需考虑循环判定条件;对于嵌套循环,循环体内计算时间所有循环次数。

② 非递归算法的空间复杂度估算:

辅助变量〈不包括输入/输出变量)。

(5)递归:
① 递归的定义:

子程序(或函数)直接调用自己或通过一系列调用语句间接调用自已,称为递归。

直接或间接调用自身的算法称为递归算法。

② 采用递归算法来求解问题的一般步骤:

分析问题,寻找递归关系;

找出停止条件;

构建递归体。

③ 递归应用实例:

Fibonacci数列;

Hanoi塔;

归并排序等。

④ 递归算法的时间复杂性分析:

后向代入法:从n出发,利用递推关系计算。

猜测代入法:先猜测一个界,然后用数学归纳法证明该界是正确的。(CLRS p37,47)

递归树方法:基于递归公式。容忍少量的“草率(sloppiness)"。结点表示所花费代价,计算整棵树的代价和即得。(另附ppt)

主定理方法:给出如下递归形式的“食谱”性的方法(三种情况)(另附ppt)

⑤ 递归算法的空间复杂性分析:

辅助变量、递归栈(不包括输入/输出变量)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本书是国际算法大师乌迪·曼博(Udi Manber)博士撰写的一本享有盛誉的著作。全书共分12章:第1章到第4章为介绍性内容,涉及数学归纳法、算法分析、数据结构等内容;第5章提出了与归纳证明进行类比的算法设计思想;第6章到第9章分别给出了4个领域的算法,如序列和集合的算法、图算法、几何算法、代数和数值算法;第10章涉及归约,也是第11章的序幕,而后者涉及NP完全问题;第12章则介绍了并行算法;最后是部分习题的答案及参考文献。本书的特色有二,旨在提高读者的问题求解能力,使读者能够理解算法设计的过程和思想:一是强调算法设计的创造性过程,注重算法设计背后的创造性思想,而不拘泥于某个具体算法的详细讨论;二是将算法设计类比于定理归纳证明,揭示了算法设计的基本思想和本质。 本书的组织结构清晰且易于理解,强调了创造性,具有浓郁特色,时至今日仍有其巨大的价值,并且适合作为计算机及相关专业算法和高级算法课程的教材。 第1章 论 第2章 数学归纳法 2.1 言 2.2 三个简单的例子 2.3 平面内区域的计数 2.4 简单的着色问题 2.5 复杂一些的加法题 2.6 一个简单的不等式 2.7 欧拉公式 2.8 图论中的一个问题 2.9 格雷码 2.10 在图上寻找无重边的路 2.11 数学平均数和几何平均数定理 2.12 循环不变量:将十进制数转换为二进制数 2.13 常见的错误 2.14 小结 第3章 算法分析 3.1 言 3.2 符号O 3.3 时间与空间复杂度 3.4 求和 3.5 递推关系 3.5.1 巧妙地猜测 3.5.2 分治关系 3.5.3 涉及全部历史的递推关系 3.6 一些有用的证明论据 3.7 小结 第4章 数据结构简介 4.1 言 4.2 基本数据结构 4.2.1 元素 4.2.2 数组 4.2.3 记录 4.2.4 链表 4.3 树 4.3.1 树的表示 4.3.2 堆 4.3.3 二叉搜索树 4.3.4 AVL树 4.4 散列 4.5 合并?查找问题 4.6 图 4.7 小结 第5章 基于归纳的算法设计 5.1 言 5.2 多项式求值 5.3 最大导出子图 5.4 寻找一对一映射 5.5 社会名流问题 5.6 分治算法:轮廓问题 5.7 在二叉树中计算平衡因子 5.8 寻找最大连续子序列 5.9 增强归纳假设 5.10 动态规划:背包问题 5.11 常见的错误 5.12 小结 第6章 序列和集合的算法 6.1 言 6.2 二叉搜索的几种形式 6.2.1 纯二叉搜索 6.2.2 循环序列的二叉搜索 6.2.3 二叉搜索特殊下标 6.2.4 二叉搜索长度未知的序列 6.2.5 重叠子序列问题 6.2.6 解方程 6.3 内插搜索 6.4 排序 6.4.1 桶排序和基数排序 6.4.2 插入排序和选择排序 6.4.3 归并排序 6.4.4 快速排序 6.4.5 堆排序 6.4.6 排序问题的下界 6.5 顺序统计 6.5.1 最大数和最小数 6.5.2 查找第k小的数 6.6 数据压缩 6.7 串匹配 6.8 序列比较 6.9 概率算法 6.9.1 随机数 6.9.2 着色问题 6.9.3 将拉斯维加斯算法变换成确定性算法 6.10 查找众数 6.11 三个展现有趣证明方法的问题 6.11.1 最长递增序列 6.11.2 查找集合中两个最大的元素 6.11.3 计算多重集合的模 6.12 小结 第7章 图算法 7.1 言 7.2 欧拉图 7.3 图的遍历 7.3.1 深度优先搜索 7.3.2 广度优先搜索 7.4 拓扑排序 7.5 单源最短路径 7.6 最小代价生成树 7.7 全部最短路径 7.8 传递闭包 7.9 图的分解 7.9.1 双连通分支 7.9.2 强连通分支 7.9.3 利用图分解的例子 7.10 匹配 7.10.1 非常稠密图中的完美匹配 7.10.2 偶图匹配 7.11 网络流量 7.12 哈密尔顿旅行 7.12.1 反向归纳 7.12.2 在非常稠密图中找哈密尔顿回路 7.13 小结 第8章 几何算法 8.1 言 8.2 判定点是否在多边形内部 8.3 构造简单多边形 8.4 凸包 8.4.1 直接方法 8.4.2 礼品包裹算法 8.4.3 Graham扫描算法 8.5 最近点对 8.6 水平线段和竖直线段的交点 8.7 小结 第9章 代数和数值算法 9.1 言 9.2 求幂运算 9.3 欧几里得算法 9.4 多项式乘法 9.5 矩阵乘法 9.5.1 Winograd算法 9.5.2 Strassen算法 9.5.3 布尔矩阵 9.6 快速傅里叶变换 9.7 小结 第10章 归约 10.1 言 10.2 归约的例子 10.2.1 简单字符串匹配问题 10.2.2 特殊代表集 10.2.3 关于序列比较的归约 10.2.4 在无向图中寻找三角形 10.3 有关线性规划的归约 10.3.1 概述与定义 10.3.2 归约到线性规划的例子 10.4 下界的归约 10.4.1 寻找简单多边形算法复杂度的下界 10.4.2 关于矩阵的简单归约 10.5 常见的错误 10.6 小结 第11章 NP完全问题 11.1 言 11.2 多项式时间归约 11.3 非确定性和Cook定理 11.4 NP完全性的证明例子 11.4.1 顶点覆盖问题 11.4.2 支配集问题 11.4.3 3SAT问题 11.4.4 团问题 11.4.5 3着色问题 11.4.6 一般经验 11.4.7 更多的NP完全问题 11.5 处理NP完全问题的技术 11.5.1 回溯法和分枝限界法 11.5.2 确保性能的近似算法 11.6 小结 第12章 并行算法 12.1 言 12.2 并行计算模型 12.3 共享存储器算法 12.3.1 并行加 12.3.2 寻找最大数的算法 12.3.3 并行前缀问题 12.3.4 在链表中查寻秩 12.3.5 欧拉遍历技术 12.4 互连网络上的算法 12.4.1 阵列上的排序 12.4.2 排序网络 12.4.3 在树中查找第k个最小元素 12.4.4 网孔上的矩阵乘法 12.4.5 超立方体中的路由 12.5 脉动计算 12.5.1 矩阵与向量相乘 12.5.2 卷积问题 12.5.3 序列的比较 12.6 小结 部分习题答案 参考文献
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值