第一章 绪论
1.1 性能分析和度量
1.1.1 算法的性能标准
判断一个算法优劣的标准:
1. 正确性:要求算法能够正确的执行预先规定的功能和性能要求。
2. 可使用性:要求算法能够很方便的使用。用户友好性。要有良好的界面,完备的用户文档。
3. 可读性:要求算法应该是可读的,这个是理解、测试和修改算法的需要。
4. 效率:算法的效率主要指算法执行时计算机资源的消耗,包括存储和运行时间的开销,前者叫算法的空间代价,后者叫做算法的时间代价。
5. 健壮性:要求在算法中加入对输入参数、打开文件、读文件记录、子程序调用状态进行自动检错、报错并通过与用户对话来纠错的功能(容错或例外处理)。
1.1.2 算法的后期测试
算法效率的度量分为事前估测和后期测试。后期测试主要通过在算法中的某些部位插装时间函数(如time())来测定算法完成某一规定功能所需要的时间。
#include <iostream>
#include <time.h>
using namespace std;
int seqsearch(int a[],int n,int x)
{
int i=0;
while(i<n&&a[i]!=x)
{
i++;
}
if(i==n)
return -1;
return
i;
}
void TimeSearch()
{
int a[1001],n[20];
long r[20]={300000,300000,200000,200000,100000,100000,100000,80000,80000,50000,50000,25000,15000,15000,10000,7500,7000,6000,5000,5000};
for(int j=1;j<=1000;j++)
{
a[j]=j;//初始化a
}
for(int j=0;j<10;j++)//给n赋值
{
n[j]=10*j;
n[j+10]=100*(j+1);
}
cout<<"n totalTime runTime"<<endl;
for(int j=1;j<20;j++)//得到计算时间
{
long start,stop;
time(&start);// 开始计时
for(long b=1;b<r[j];b++)
{
int k=seqsearch(a,n[j],0);//不成功的查询
}
time(&stop);//停止计时
long totalTime=stop-start;
float runTime=(float)(totalTime)/(float)(r[j]);//总时间除以重复执行次数
cout<<" "<<n[j]<<" "<totalTime<<" "<<runTime<<endl;
}
cout<<"Times are in hundredths of a second."<<endl;
}
int main()
{
TimeSearch();
}
1.1.3 算法的事前估算
算法复杂性的度量和计算时间与存储需求相关,属于事前估计。它可分为空间复杂度度量和时间复杂度度量。空间复杂度(Space Complexity)是指当问题的规模以某种单位从1增加到n时,解决这个问题的算法在执行时所占用的存储空间也以某种单位有1增加到
1.1.4 空间复杂度度量
程序所需要的空间包括:
1. 固定部分:这个部分空间的大小与输入输出的个数多少、数值大小无关。主要包括存放程序指令代码的空间,常数、简单变量、固定成分(如数组元素、结构成分、对象的数据成员等)变量所占用的空间。
2. 可变部分:这个部分空间主要包括其尺寸与实例特性有关的成分变量所占用空间、引用变量所占用的空间,以及递归栈所用的空间,哈有在算法运行中通过new和delete命令动态使用的空间。
1.1.5 时间复杂度度量
一个算法所用的时间等于编译时间加上运行时间。
算法的运行时间涉及到加、减、乘、除、转移、存、取、等基本的运算。运行时间主要从程序结构着手,统计算法程序步数。
程序步(program step)是指在语法上或语义上有意义的一段指令序列,而且这段指令序列的执行时间与实例特性无关。
1. 注释:程序步数为0,因它是非执行语句。
2. 声明语句:程序步数为0。
3. 表达式:如果表达式中不包含函数调用,则程序步数为1。如果表达式中包含函数调用,总的程序步数要包括分配给函数调用的程序步数。
4. 赋值语句:<变量>:=<表达式>的程序步数与表达式的程序步数相同,但如果赋值语句中的变量是数组或字符串(字符数组),则赋值语句的程序步数等于变量的体积加上表达式的程序步数。
5. 循环语句:若仅考虑循环控制部分,则有三种形式:
While与do语句,控制部分一次执行的程序步数等于<表达式>的程序步数。
For语句,控制部分一次执行的程序步数为1。
6. Swith语句。
7. If_else语句。
8. 函数执行语句。
9. 动态存储管理语句。
10. 函数调用语句。步数为0
11. 转移语句。
1.1.6 时间复杂度的渐进表示法
要确定一个程序的准确的程序步数是非常困难的,而且不是很必要的,因为程序步数这个概念本身不是一个精确的概念。
1.1.7 渐进的空间复杂度