1、离散数学,黄晓宇 HuangS,本讲内容,算法简介 算法例子 算法分析 递归算法,算法一组有限的指令集合,输入:算法接受输入。 输出:算法产生输出。 精确性:步骤被精确描述。 确定性:每步执行的结果是惟一的,且只依赖于输入和前面步骤执行的结果。 有限性:算法可以终止,也就是在执行有限多条指令后停止。 正确性:算法生成的输出结果是正确的,也就是算法可以正确地求解问题。 一般性:算法适应于一组输入。,算法示例三数排序,1. large = a. 2. If b large, then large = b. 3. If c large , then large = c. 这个算法的思想是对这些数一个
2、一个地检查,将所见的最大数赋值给变量large。在算法停止时,large 就等于这三个数中最大的了,跟踪,a=1, b=5, c=3 a=1, b=5, c=91. large = a. 2. If b large, then large = b. 3. If c large , then large = c.,x=,算法正确性证明,算法描述:在数列s1,., sn 中找出最大的一个。 输入:s, n 输出:large(序列s 中的最大值) max (s, n)large = s1for i = 2 to nif (si large)large = sireturn large ,算法正确性证
3、明(二),循环不变式:在循环的每次迭代前后均为真的谓词 large=maxs1,., sn ,算法正确性证明(三)归纳,平凡情况(i = 1)large 是序列中的最大值。 假设large是子序列s1,., si 中的最大值。 假如i large,赋值large si+1;(2)si+1 large,算法不改变large 的值。因此, large=maxs1,., sn 是一个循环不变量。 for 循环在i = n 时结束,算法正确。,文本搜索,假设给定一个文本t(例如一个文档),在t 中找出特定词组p 首次出现的位置。,text_search (p, m, t, n)for i = 1 to
4、 n - m + 1j = 1;while(t i+j-1 = p j)j = j + 1;if(j m) return j;return 0 ,插入排序,假设插入排序的输入是s1,., sn,目标是按非递减顺序将数据排序。 在插入排序的第i 次迭代后,序列的前一部分s1,., si会被重新安排使得它有序。插入排序接下来将s i + 1插入s1,., si,使得s1,., si, si+1 也是有序的。,时空分析,在插入排序算法中,for 循环执行n - 1 次,但是对于一个特定的i 值,while 循环执行的次数依赖于输入。 例如,如果输入的序列已经按非递减顺序排列,val sj总是fals
5、e,while 的循环体永远不被执行,称这个时间为最好情形执行时间;另外,如果这个序列是按递减顺序排序的,val sj, 总是true,while 的循环体执行最大次数。(当第i 次迭代时for 循环中while 循环执行i - 1 次)。称这个时间为最坏情形执行时间。,随机算法,一个随机算法(randomized algorithm)并不要求每一步的执行中间结果被惟一决定且只依赖于输入和前面步骤的执行结果。 根据定义,当执行一个随机算法时,在某些点上,算法做出随机选择。,随机算法(二),rand (i, j):返回在整数i 和j 之间的(包含i 和j)一个随机整数。,算法的分析,一个计算机程
6、序,即便是正确的,也可能是不可用的,因为执行这个程序需要的时间或者存储这个程序的数据、变量等需要的空间太大了。 例:列举一个N元集合的所有子集(编程实现),确定一个计算机程序性能,估计执行一个算法需要的精确时间是很困难的 用程序输入的规模作为估算参数而不是直接利用程序的输入。例如,若输入是一个包含n 个元素的集合,称输入的规模是n。 在所有输入规模为n 时执行算法需要的最少时间称为输入规模为n时的最好情形执行时间。 在输入规模为n时执行算法需要的最大时间称为输入规模为n时的最坏情形执行时间。 平均时间。,令f 和g 是定义域为1, 2, 3,.上的函数 若存在C1,对所有有限的正整数n满足:
7、| f(n)| C1 |g(n)| ,则称 f(n)最大以g(n)为阶, f(n)=O(g(n) 若存在C2对所有有限的正整数n满足:| f(n)| C2 |g(n)|,则称 f(n)最小以g(n)为阶,f(n)= (g(n),数学定义,除了常数因子和有限数之外,f 的上界是g,写成f (n) = O(g(n)。也称g 是f 的一个渐近上界。 除了常数因子和有限数之外,f 的下界是g,写成f (n) = (g(n)。也称g 是f 的一个渐近下界。 除了常数因子和有限数之外,f的上下界均为g,写成f (n) = (g(n)。也称g是f的一个渐近紧密界。,数学定义(二),数学定义(三),如果f (
8、n) = O(g(n),可得出结论除了对某些常量因子和有限数之外,f 的上界是g,所以g 至少和f 的增长一样快。例如,如果f (n) = n, g(n) = 2n,那么f (n) = O(g(n),但是g 比f 增长快得多。另一方面,如果f (n) = (g(n),可得出结论:除了对某些常量因子和有限数之外,f 的上下界是g,所以f 和g 的增长一样快。注意n = O(2n),但是n (2n)。,复杂度计算:夹逼法,f(n)=(g(n) iff f(n)=O(g(n) and f(n)= (g(n) 例1:P163 例4.3.3 60n2+5n+1 = (n2),对ak、 ak-1、 a1、
9、a00(*) aknk + ak-1nk-1+ + a1n1+a0 = (nk),(*)是否必须?,例:给出语句x = x + 1 的执行次数关于n 的表示,(lg n),例:给出语句x = x + 1 的执行次数关于n 的表示,Input: s1,s2,sn, n, key Output : index of key,procedure linear_search(s,n,key)for i:= 1 to n doif key = si thenreturn(i)return(0) end linear_serach,讨论,P174 30 算法的思路 复杂度 P17669,递归算法,一个递归
10、函数(伪代码)是调用自身的函数。一个递归算法是包含递归函数的算法。 递归算法的基本思想:分而治之。 即将问题分解成与初始问题同类型的子问题来求解,每一个子问题又可以继续分解依次类推,直到这个过程得到的子问题可以通过一个直接的办法求解。 最后,通过组合子问题的解就可以得到初始问题的解。,阶乘计算: n!,n! = n(n - 1) (n - 2)21,= n(n - 1)!,阶乘计算(二),N!(N-1)! (N-2)! (N-3)! ,int Factorial(int n) return n*Factorial(n-1); ,?,阶乘计算(三),int Factorial(int n) if
11、(n=1) return 1;return n*Factorial(n-1); ,递归算法的两大要素,递归函数 一个递归函数是一个调用自身的函数。写出一个递归函数的关键是找到原来较大问题的一个较小规模的例子。 终止条件,递归:机器人,一个机器人每步可以走1 米或者2 米,计算机器人走n 米所用方法的数目。,递归:机器人(二),递归函数:令walk(n)代表机器人走n 米所用方法的数目,如果这个机器人从走1 米一步开始,剩下n - 1 米的距离;根据定义,剩下的路程有walk(n - 1)种方法。类似地,如果机器人以2 米一步开始,剩下n - 2 米的距离,这时,剩下的路程有walk(n - 2) 种方法。 终止条件: walk(1) = 1, walk(2) = 2 。,递归:机器人(三),