算法
1.算法(Algorithm)的定义
算法是规则的有限集合, 是为解决特定问题而规定的一系列操作
2.算法的特性
(1) 有限性:有限步骤之内正常结束,不能形成无穷循环。
(2) 确定性:算法中的每一个步骤必须有确定含义, 无二义性。
(3) 输入: 有多个或0个输入。
(4) 输出: 至少有一个或多个输出。
(5) 可行性: 原则上能精确进行, 操作可通过已实现的基本运算执行有限次而完成。在算法的五大特性中, 最基本的是有限性、 确定性和可行性。
3.算法设计的要求
1) 算法的正确性
所设计的程序没有语法错误;
所设计的程序对于几组输入数据能够得出满足要求的结果;
所设计的程序对于精心选择的典型、 苛刻而带有刁难性的几组输入数据能够得到满足要求的结果。
程序对于一切合法的输入数据都能产生满足要求的结果。
2) 可读性 :方便阅读。
3) 健壮性 :当输入数据非法时,算法也能适当地做出反应或进行处理,而不会产生不适当的结果。
4) 高效率和低存储量
4. 算法描述的工具
概述:算法+数据结构=程序
4.1 算法、 语言和程序的关系
(1) 算法: 描述了数据对象的元素之间的关系(包括数据逻辑关系、 存储关系描述)。
(2) 描述算法的工具:算法可用自然语言、框图或高级程序设计语言进行描述。 自然语言简单但易于产生二义,框图直观但不擅长表达数据的组织结构, 而高级程序语言则较为准确但又比较严谨。
(3) 程序是算法在计算机中的实现(与所用计算机及所用语言有关)。 程序=数据结构+算法
4.2 设计实现算法过程的步骤
· 找出与求解有关的数据元素之间的关系(建立结构关系)。
· 确定在某一数据对象上所施加的运算。
· 考虑数据元素的存储表示。
· 选择描述算法的语言。
· 设计实现求解的算法, 并用程序语言加以描述。
4.3 描述算法的语言选择
高级语言描述算法具有严格、准确的优点,但用于描述算法也有语言细节过多的弱点。为此,采用类语言的形式。类语言是接近于高级语言而又不是严格的高级语言,具有高级语言的一般语句设施,撇掉语言中的细节。
本书采用c语言描述。
5 对算法作性能评价
评价算法的标准
评价一个算法主要看这个算法所占用机器资源的多少,而这些资源中时间代价与空间代价是两个主要的方面,通常是以算法执行所需的机器时间和所占用的存储空间来判断一个算法的优劣。
对算法作性能评价
对问题规模和该算法在运行时所占的空间S与所耗费的时间T给出一个数量关系的评价。
问题规模N对不同的问题其含义不同,对矩阵是阶数, 对多项式运算是多项式项数,对图是顶点个数,对集合运算是集合中的元素个数。
5.1 关于算法执行时间
一个算法的执行时间大致上等于其所有语句执行时间的总和,对于语句的执行时间是指该条语句的执行次数和执行一次所需时间的乘积。
不是针对实际执行时间的精确地算出算法执行具体时间,而是针对算法中语句的执行次数做出估计,从中得到算法执行时间的信息。
5.2. 语句频度
语句频度是指该语句在一个算法中重复执行的次数。
5.3 算法的时间复杂度
通常的做法是,以算法中基本操作重复执行的次数作为算法的时间度量。一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数f(n),算法的时间量度记作
T(n)=O(f(n))
它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐近
时间复杂度简称时间复杂度。
撇开与计算机软、硬件有关的因素,影响算法时间代价的最主要的因素是问题的规模。问题规模是指算法求解问题的输入量(或初始数据量)。
问题的基本操作应是其重复执行次数和算法的执行时间成正比的原操作。
由于算法的时间复杂度考虑的只是对于问题规模n的增长率,则在难以精确计算基本操作执行次数的情况下,只需求出它关于n的数量级即可。
当有若干个循环语句时,算法的时间复杂度是由嵌套层数最多的循环语句中最内层语句的执行次数(频度)决定的。
5.4 时间复杂度的一些运算规则
一些规则(引自:时间复杂度计算)
1) 加法规则
T(n,m) = T1(n) + T2(n) = O (max ( f(n), g(m) )
2) 乘法规则
T(n,m) = T1(n) * T2(m) = O (f(n) * g(m))
3) 一个特例(问题规模为常量的时间复杂度)
在大O表示法里面有一个特例,如果T1(n) = O(c), c是一个与n无关的任意常数,T2(n) = O ( f(n) ) 则有
T(n) = T1(n) * T2(n) = O ( c*f(n) ) = O( f(n) )
也就是说,在大O表示法中,任何非0正常数都属于同一数量级,记为O(1)。
5.5 常用的时间复杂度频率计数
5.6 算法的存储空间需求
空间复杂度:算法所需存储空间的度量,记作:
S(n)=O(f(n))
其中n为问题的规模。
一个程序执行需要空间:
①程序(指令、常数、变量)
②输入数据所占空间 ----和算法无关时不考虑
③辅助存储空间 ----主要考虑
5.7 时间和空间的折衷
在算法设计分析中,还涉及一个“时空资源的折衷原理”。这个原理可以简述如下:
对于同一个问题求解,一般会存在多种算法。而这些算法在时间和空间开销上的优劣往往表现出“时空折衷”的性质。所谓“时空折衷”是指,为了改善一个算法的时间开销,往往可以增大空间开销为代价;反之亦然。
6. 结构化程序设计与函数的模块化
结构化程序设计 :是为使程序具有合理的结构,以保证程序正确性而规定的一套程序设计的方法 。
程序设计的实质:算法+数据结构=程序
即“程序是在数据的特定表示方式的基础上,对抽象算法的具体描述”。
程序结构=控制结构+数据结构
7. 面向对象与抽象数据类型
面向对象的概念:
面向对象=对象+类+继承+通信
对象:指在应用问题中出现的各种实体、事件、规格说明等 。
类:具有相同属性和服务的对象
继承:是面向对象方法的最有特色的方面。
结构化与面向对象开发方法的不同点
结构化的开发方法:是面向过程的开发方法,首先着眼于系统要实现的功能。
面向对象的开发方法:
首先着眼于应用问题所涉及的对象,包括对象、对象属性和要求的操作,从而建立对象结构和为解决问题需要执行的时间序列。
抽象数据类型与问题求解方法
抽象数据类型(简称ADT)是指基于一类逻辑关系的数据类型以及定义在这个类型之上的一组操作。
一个抽象数据类型确定了一个模型,但将模型的实现细节隐藏起来;它定义了一组运算,但将运算的实现过程隐藏起来。
用抽象数据类型的概念来指导问题的求解过程:
算法描述规范与设计风格
1. 算法表示格式与函数模块化
一个全局变量方式带出的例子
int MIN; /* 全局变量 */
int fun1(int a[], int n)
/*通过函数return返回最大值,通过全局变量MIN带回最小值*/
{ int i,max;
max=MIN=a[0]; //给最大值最小值赋初值
for (i=0;i
{
if(a[i]>max) max=a[i];
if (a[i]
}
return(max);
}
地址方式带出:
数组方式带出的例子
int *fun2(int a[],int n)
/*将最大、最小值放到数组b中,通过return返回*/
{ static int b[2];
b[0]=b[1]=a[0]; //给最大值最小值赋初值
int i;
for (i=1;i { if (a[i]>b[0]) b[0]=a[i]; if (a[i]
b[1]=a[i]; } return(b); } 指针方式带出的例子 Data *fun3(int a[],int n) /*将最大、最小值放到结构体指针p中,通过return返回*/ { Data *p; int i; p=(Data *)malloc(sizeof(Data *)); //指针初始化 p->max=p->min=a[0]; //给最大值最小值赋初值 for(i=1;i { if (a[i]>p->max) p->max=a[i]; if (a[i] p->min=a[i]; } return(p); } 结构体方式带出的例子 Data fun4(int a[],int n) /*将最大、最小值放到结构体p中,通过结构体p带回返回值*/ { Data p; int i; p.max=p.min=a[0]; //给最大值最小值赋初值 for(i=1;i { if (a[i]>p.max) p.max=a[i]; if (a[i] p.min=a[i]; } return(p); } 8. 数据结构与其它课程关系图: 9.总结: 9.1.掌握数据结构的基本概念 数据结构包括数据的逻辑结构、存储结构和运算集合这三个部分。 9.2. 注意逻辑结构与存储结构的区别