当前位置:文档之家› 计算机算法设计与分析总复习

计算机算法设计与分析总复习


在最坏情况下,算法randomizedSelect需要O(n2)计算时间 但可以证明,算法randomizedSelect可以在O(n)平均时间内 找出n个输入元素中的第k小元素。
线性时间选择
将n个输入元素划分成n/5个组,每组5个元素,只可能 有一个组不是5个元素。用任意一种排序算法,将每组中的 元素排好序,并取出每组的中位数,共n/5个。 递归调用select来找出这n/5个元素的中位数。如果 n/5是偶数,就找它的2个中位数中较大的一个。以这个 元素作为划分基准。

基于分治法的递归
2.1 递归的概念
例 Fibonacci数列 无穷数列1,1,2,3,5,8,13,21,34,55,„„,称为 Fibonacci数列。它可以递归地定义为: 边界条件 1 n0 F ( n) 1 n 1 F (n 1) F (n 2) n 1 递归方程 第n个Fibonacci数可递归地计算如下: int fibonacci(int n) { if (n <= 1) return 1; return fibonacci(n-1)+fibonacci(n-2); }
线性时间选择问题

问题描述:给定线性集中n个元素和一个整数
k,要求找出这n个元素中第k小的元素,即如果 将这n个元素依其线性序排列时,排在第k个位 置的元素即为我们要找的元素。 当k=1时,即找最小元素;当k=n时,即找最大 元素;当k=(n+1)/2时,称为找中位数。
线性时间选择
template<class Type> Type RandomizedSelect(Type a[],int p,int r,int k) { if (p==r) return a[p]; int i=RandomizedPartition(a,p,r), j=i-p+1; if (k<=j) return RandomizedSelect(a,p,i,k); else return RandomizedSelect(a,i+1,r,k-j); }
合并排序
基本思想:将待排序元素分成大小大致相同的2个子集合,分 别对2个子集合进行排序,最终将排好序的子集合合并成为所 要求的排好序的集合。 复杂度分析 O(1) n 1 public static void T (n) 2T (n / 2) O(n) n a[], int left, int right) mergeSort(Comparable 1 { T(n)=O(nlogn) 渐进意义下的最优算法 if (left<right) {//至少有2个元素 int i=(left+right)/2; //取中点 mergeSort(a, left, i); mergeSort(a, i+1, right); merge(a, b, left, i, right); //合并到数组b copy(a, b, left, right); //复制回数组a } }
分治算法总体思想
分治法的设计思想是,将一个难以直接解决的 大问题,分割成一些规模较小的相同问题,以 便各个击破,分而治之。
分治法的适用条件
分治法所能解决的问题一般具有以下几个特征:

该问题的规模缩小到一定的程度就可以容易地解 决; 该问题可以分解为若干个规模较小的相同问题, 即该问题具有最优子结构性质 利用该问题分解出的子问题的解可以合并为该问 题的解;
则记作f(n) = Ο (g(n))
含义: 如果算法用n值不变的同一类数据在某台机器上运行时,所 用的时间总是小于|g(n)|的一个常数倍。所以g(n)是计算 时间f(n)的一个上界函数。 f(n)的数量级就是g(n)。 f(n)的增长最多像g(n)的增长那样快 试图求出最小的g(n),使得f(n) = Ο (g(n))。
3)“平均情况”限界函数
定义1.3 如果存在正常数c1,c2和n0,对于所有的
n≥n0,有
c1|g(n)| ≤|f(n)| ≤ c2|g(n)|
则记作
f (n) ( g (n))
含义: 算法在最好和最坏情况下的计算时间就一个常数因子范 围内而言是相同的。可看作: 既有f(n) = Ω (g(n)),又有f(n) = Ο (g(n)) 记号表明算法的运行时间有一个较准确的界
算法渐近复杂性
定义 1.2 设算法的执行时间 T ( n ) ,如果存在 T * ( n ) , 使得
T (n ) T *( n ) lim 0 n T (n )
就称 T * ( n ) 为算法的渐近时间复杂性。
1)上界函数
有 |f(n)| ≤ c|g(n)|
定义1 如果存在两个正常数c和n0,对于所有的n≥n0



该问题所分解出的各个子问题是相互独立的,即 子问题之间不包含公共的子问题。
分治法的基本步骤
(1)分解:将原问题分解为若干个规模较小
,相互独立,与原问题形式相同的子问题;
(2)解决:若子问题规模较小而容易被解决 则直接解,否则递归地解各个子问题; (3)合并:将各个子问题的解合并为原问题 的解。
线性时间选择问题算法
上述Partition算法可用来求选择问题的有效解。 如果划分元素v测定在A(j)的位置上,则有j1个元素小于或等于A(j),且有n-j 个元素大于或 等于A(j)。因此,若k<j,则第k小元素在A(1: j-1)中,再对之进一步划分。 若k=j,则A(j)就是第k小元素 若k>j,则第k小元素在A(j+1:n)中,再对之进一 步划分。
说明:当n取值较大时,指数时间算法和多项式
时间算法在计算时间上非常悬殊。
典型的计算时间函数曲线
2)下界函数
定义1.2 如果存在两个正常数c和n0,对于所有的 n≥n0,有
|f(n)| ≥ c|g(n)|
则记作f(n) = Ω (g(n)) 含义:


如果算法用n值不变的同一类数据在某台机器上运行时 所用的时间总是不小于|g(n)|的一个常数倍。所以g(n 是计算时间f(n)的一个下界函数。 f(n)的增长至少像g(n)的增长那样快 试图求出“最大”的g(n),使得f(n) = Ω (g(n))。
O(1) n 1 T (n) kT (n / k ) f (n) n 1
通过迭代法求得方程的解: T (n) n bnlog kn
二分搜索技术
给定已按升序排好序的n个元素a[0:n-1],现要在这n个元素中找 出一特定元素x。
据此容易设计出二分搜索算法:
算法复杂度分析: template<class Type> 每执行一次算法的while int BinarySearch(Type a[], const Type& x, int l, int r) 循环, 待搜索数组的大 { 小减少一半。因此,在最 while (r >= l){ 坏情况下,while循环被 int m = (l+r)/2; if (x == a[m]) return m; 执行了O(logn) 次。循环O(1) 时间, else l = m+1; 因此整个算法在最坏情况 } 下的计算时间复杂性为 return -1; O(logn) 。 }
分治法的复杂性分析
一个分治法将规模为n的问题分成k个规模为n/k的子问题 去解。设分解阀值n0=1,且adhoc解规模为1的问题耗费1个 单位时间。再设将原问题分解为k个子问题以及用merge将k 个子问题的解合并为原问题的解需用f(n)个单位时间。用 T(n)表示该分治法解规模为|P|=n的问题所需的计算时间, 则有:

任何一种程序设计语言都可以实现任何 一个算法
算法的有穷性意味着不是所有的计算机 程序都是算法

问题求解(Problem Solving)
理解问题 精确解或近似解 选择数据结构 算法设计策略 设计算法 证明正确性 分析算法 设计程序
算法复杂性
= 算法所需要的计算机资源
=时间复杂性+空间复杂性
一般只考虑三种情况下的时间性:最坏情况、 最好情况和平均情况下的复杂性,分别记为 Tmax(n)、 Tmin(n)和Tavg(n)
合并排序
算法mergeSort的递归过程可以消去。
初始序列
[49] [38] [65] [97] [76] [13] [27]
第一步
[38 49]
[65 97]
[13 76]
[27]
第二步
[38 49 65 97]
[13 27 76]
第三步
[13 27 38 49 65
76 97]
快速排序
private static void qSort(int p, int r) { if (p<r) { int q=partition(p,r); //以a[p]为基准元素将a[p:r]划分成 3段a[p:q-1],a[q]和a[q+1:r],使得a[p:q-1]中任何元素小于等 于a[q],a[q+1:r]中任何元素大于等于a[q]。下标q在划分过 程中确定。 qSort (p,q-1); //对左半段排序 qSort (q+1,r); //对右半段排序 } }
最优算法

问题的计算时间下界为(f(n)),则计算 时间复杂性为O(f(n))的算法是最优算法。

例如,排序问题的计算时间下界为 (nlogn),计算时间复杂性为O(nlogn)的
排序算法是最优算法。
第2章 递归与分治策 略
2.1 递归的概念
函数自身给出定义的函数称为递归函数。

直接或间接地调用自身的算法称为递归算法。 基于归纳法的递归
算法 消去递归的合并排序算法
输入:具有个元素的数组A[]
相关主题