这一章我们主要讨论
1.如何估计一个程序所需要的时间。
2.如何将一个程序的运行时间从天或年降低到秒。
3.粗心地使用递归的后果。
4.将一个数自乘得到其幂以及计算两个数的最大公因数的非常有效的算法。
一.所需了解的五个定义
1.定义:Ο(g(n))={f(n) | 如果存在正常数c和正整数n0,使得当n>=n0时,0<=f(n)<=cg(n)恒成立}。简称大O表示:即函数g(n)是函数f(n)的上界。
2.类似的如 :Ω(g(n))={f(n) | 如果存在正常数c和正整数n0,使得当n>=n0时,0<=cg(n)<=f(n)恒成立}。简称大Ω表示,即即函数g(n)是函数f(n)的下界。
3.Θ:O g(n)=f(n) && Ω(g(n))=f(n) 则 Θ g(n) = f(n)。
4.o(小o)O g(n)=f(n) && Θ (g(n))!=f(n)。
5.w (小Ω) Ω g(n)=f(n) && Θ (g(n))!=f(n)。
二.相对增长率的计算以及一些重要结论
1.Lim(n趋于无穷大) g(n)/f(n) 结果有三种情况 1.常数 Θ g(n) = f(n) 2.无穷大 O g(n)=f(n) 3. 0 Ω g(n)=f(n) 。
2.对于任意常数k,(logN)的k次方=O(N).
3.复杂度与时间效率的关系:
c < log2n < n < n*log2n < n2 < n3 < 2n(2的n次方) < 3n < n! (c是一个常量)
三.Average T(n) 与 Worst T(n)
1.Average T(n) < =Worst T(n)
2.Average T(n) =Σp(i)*t(i).
四.运行时间的对数
1.一般法则:如果一个算法用常数时间O(1)将问题的大小消减为其中一部分(通常为1/2),那么该算法就是o(logN)的。
例如:对分查找(折半查找)具体的算法:
int BinarySearch(const ElementType A[],Elemtype x, int n )
{
int low,mid,high;
low =0,high = n-1;
while(low<=high)
{
mid =(low + high)/2;
if(A[mid]<x)
low=mid+1;
else
if(A[mid]>x)
high = mid -1;
else
return mid;
}
return NOTFOUND;
}
五.案例
1.最大序列和
给一组整数求出其中最大的子序列和。
思路一:迭代 for 0 to n. (a[n])
int max =0, b =0;
if(max>b) max =b;
b+= a[i] ;
思路二:递归。将该序列分为两部分(左右),max 只可能出现在 左部分,右部分,或中间三种可能。
1.左右部分可利用递归实现。
2.有点复杂的是处理中间部分,可分为左边界到右半部分第一个元素,或左半部分最后一个元素到右边界,或中间部分。
具体代码实现:
static int
MaxSubsum(const int a[], int left,int right)
{
int MaxLeftSum, MaxRightSum;
int MaxleftBordersum, MaxrightBordersum;
int leftBordersum,rightBordersum;
int centre,i;
if(left == right)
if(a[left]>0)
return a[left];
else
return 0;
centre = (left + right)/2;
MaxleftSum =MaxSubsum(a[], left,centre);//类似于折半递归的思路
MaxrightSum = MaxSubsum(a[],centre+1,right);
// 中间部分的处理
MaxleftBordersum = 0,MaxrightBordersum=0;//迭代思路一
for(i=centre;i>=left;i--)
{
leftBordersum + =A[i];
if(leftBordersum > maxleftBordersum)
maxleftBordersum = leftBordersum;
}
MaxleftBordersum = 0,MaxrightBordersum=0;//迭代思路一
for(i=centre+1;i<=right;i++)
{
rightBordersum + =A[i];
if(rightBordersum > maxrightBordersum)
maxrightBordersum = rightBordersum;
}
return max3(Maxleftsum,maxrightsum,maxrightBordersum+maxleftBordersum);
}
3.还有一种更加简单的算法,暂且不聊。
2.最大公因数求法
主要介绍欧几里得算法
unsigned int ;
GCD(unsigned int m,unsigned int n)
{
unsigned int Rem;
while(N>0)
{
Rem = m%n;
m=n;
n=Rem;
}
return M;
}
六.检验分析
1.编程实际检验
2.对N取范围 (一般为2的倍数隔开)计算T(n)/F(n),一般比值为常数则接近。