2.3.2 分析分治算法

当一个算法包含对其自身的递归调用时,我们往往可以用递归方程或递归式来描述其运行时间,该方程根据在较小输入上的运行时间来描述在规模为n的问题上的总运行时间。然后,我们可以使用数学工具来求解该递归式并给出算法性能的界。

分析算法运行时间的递归式来自基本模式的三个步骤。如前所述,我们假设T(n)是规模为n的一个问题的运行时间。若问题规模足够小,如对某个常量c,n<=c,则直接求解需要常量时间,我们将其写作O(1).假设把原问题分解成a个子问题,每个子问题是原问题的1/b.(对归并排序,a和b都为2,然而,我们将看到在许多分治算法中,a!=b)为求解一个为n/b的子问题,需要T(n/b)的时间,所以需要aT(n/b)的时间来求解a个子问题。如果分解问题成子问题需要时间D(n),合并子问题的解成原问题的解需要时间C(n),那么得到递归式

O(1)           若n<=c

T(n) =

aT(n/b)+D(n)+C(n)    其他

  归并排序算法的分析

虽然MERGE-SORT的伪代码在元素的数量不是偶数时也能正确地工作,但是假定原问题规模是2的幂,那么基于递归式的分析将被简化。这时每个分解步骤将产生规模刚好为n/2的两个子序列。

下面我们分析建立归并排序n个数的最坏情况运行时间T(n)的递归式。归并排序一个元素需要常量时间。当有n>1个元素时,我们分解运行时间如下:

分解:分解步骤仅仅计算子数组的中间位置,需要常量时间,因此,D(n)=O(n).

解决:我们递归地求解两个规模均为n/2的子问题,将贡献2T(n/2)的运行时间

合并:我们已经注意到在一个具有n个元素的子数组上过程MERGE需要O(n)的时间,所以C(n)=O(n).

当为了分析归并排序而把函数D(n)与C(n)相加时,我们是在把一个O(n)函数与另一个O(1)函数相加。相加的和是n的一个线性函数,即O(n).把它与来自"解决"步骤的项2T(n/2)相加,将给出归并排序的最坏情况运行时间T(n)的递归式:

O(1)        若n=1

T(n) =                         (2.1)

2T(n/2)+O(n)    若n>1

在第4章,我们将看到"主定理",可以用该定理来证明T(n)为O(nlgn),其中lgn代表log2 n.因为对数函数比任何线性函数增长要慢,所以对足够大的输入,在最坏情况下,运行时间为O(nlgn)的归并排序将优于运行时间为O(n^2)的插入排序。

为了直观地理解式(2.1)的解为什么是T(n)=O(nlgn),我们并不需要主定理。把递归式(2.1)重写为:

c        若n=1

T(n) =                     (2.2)

2T(n/2)+cn     若n>1

其中常量c代表求解规模为1的问题所需的时间以及在分解步骤与合并步骤处理每个数组元素所需的时间

时间: 2024-11-10 17:59:10

2.3.2 分析分治算法的相关文章

【万字博文】分析与设计:插入排序和分治算法、递归和迭代的探讨

插入排序及其解决思路 算法的作用自然不用多说,无论是在校学生,还是已经工作多年,只要想在计算机这条道路走得更远,算法都是必不可少的. 就像编程语言中的"Hello World!"程序一般,学习算法一开始学的便是排序算法.排序问题在日常生活中也是很常见的,说得专业点: 输入是:n个数的一个序列<a1,a2,...,an?1,an> 输出是:这n个数的一个全新的序列<a,1,a,2,...,a,n?1,a,n>,其特征是a,1≤a,2≤...≤a,n?1≤a,n 举

【算法】2 由股票收益问题再看分治算法和递归式

回顾分治算法 分治算法的英文名叫做"divide and conquer",它的意思是将一块领土分解为若干块小部分,然后一块块的占领征服,让它们彼此异化.这就是英国人的军事策略,但我们今天要看的是算法. 如前所述,分治算法有3步,在上一篇中已有介绍,它们对应的英文名分别是:divide.conquer.combine. 接下来我们通过多个小算法来深化对分治算法的理解. 二分查找算法 问题描述:在已排序的数组A中查找是否存在数字n. 1)分:取得数组A中的中间数,并将其与n比较 2)治:

基于分治算法的归并排序

#include <stdio.h> #include <math.h> void main() { int array[] = {1,212,35,1,456,12376,167,12,7523,71,634}; mergeSort(array, 0, 10); for(int i = 0; i < 11; i++ ) { printf("%d\n", array[i]); } } void mergeSort(int* array, int start

分治算法(一)

当我们求解某些问题时,由于这些问题要处理的数据相当多,或求解过程相当复杂,使得直接求解法在时间上相当长,或者根本无法直接求出.对于这类问题,我们往往先把它分解成几个子问题,找到求出这几个子问题的解法后,再找到合适的方法,把它们组合成求整个问题的解法.如果这些子问题还较大,难以解决,可以再把它们分成几个更小的子问题,以此类推,直至可以直接求出解为止.这就是分治策略的基本思想. 1.引例: 如果给你一个装有16枚硬币的袋子,其中有一枚是伪造的,并且那枚伪造硬币的重量和真硬币的重量不同.你能不能用最少

分治算法(思想)在数据结构中的应用

分治算法: 简单的概括就是将暂时不能解决的大问题分成许多入门的子问题, 如果子问题还是不能解决的话则继续分成子问题,直到子问题小到 可以解决为止的规模,原问题即是子问题的合并. PartOne: 用分治法打印数组a[L,......,R]. 分析: 一个循环就可以了,但是分治算法来解决该怎么做呢? 如果待打印的序列长度为 1,则可以直接打印; 如果待打印的序列长度为 N,则可将其划分为两部分; 第一部分是 1, 后N - 1 是另一个划分,以此类推,直到数组长度是 1. void print(i

五大常用算法----贪心、动态规划、分支限界、分治算法和回溯算法

五大常用算法之一:贪心算法 所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解. 贪心算法没有固定的算法框架,算法设计的关键是贪心策略的选择.必须注意的是,贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态有关. 所以对所采用的贪心策略一定要仔细分析其是否满足无后效性. 五大常用算法之二:动态规划算法 五大常用算法之三:分支限界算法

算法学习——分治算法

这是从网上查到的概念资料,先收来~ 一.基本概念 在计算机科学中,分治法是一种很重要的算法.字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并.这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)…… 任何一个可以用计算机求解的问题所需的计算时间都与其规模有关.问题的规模越小,越容易直接求解,解题所需的计算时间也越少.例如,对于n个

分治算法小总结 x

分治算法的基本思想是将一个规模为 N 的问题分解为 K 个规模较小的子问题,这些子问题相互独立且与原问题性质相同.求出子问题的解,就可得到原问题的解. ——以上来自百度百科. * 分治法解题的一般步骤:1 分解,将要解决的问题划分成若干规模较小的同类问题:- 二分法:区间对半分开2 求解,当子问题划分得足够小时,用较简单的方法解决:- 边界情况:可以直接操作3 合并,按原问题的要求,将子问题的解逐层合并构成原问题的解.- 合并操作:根据不同的题目来确定 其实这个题用冒泡排序做的,但用归并排序也能

算法系列之常用算法之一----分治算法

一.基本概念 在计算机科学中,分治法是一种很重要的算法.分治算法,字面上的解释是"分而治之",分治算法主要是三点: 1.将一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题----"分" 2.将最后子问题可以简单的直接求解----"治" 3.将所有子问题的解合并起来就是原问题打得解----"合" 这三点是分治算法的主要特点,只要是符合这三个特点的问题都可以使用分治算法进行解决(注意用词,是"