算法及其描述
2018-03-01 16:48
106 查看
一、算法
数据元素之间的关系有逻辑关系和物理关系,对应的操作有逻辑结构上的操作功能和具体存储结构上的操作实现。
通常把具体存储结构上的操作实现步骤或过程称为算法。
算法有五个重要的特性1)有穷性 2)确定性 3)可行性 4)有输入 5)有输出
算法设计应满足以下几条目标: 1)正确性 2)可使用性 3)可读性 4)健壮性 5)高效率和低存储量需求
二、 算法时间复杂度分析
通常有两种衡量算法效率的方法:事后统计法和事前估算法。但是由于事后统计法必须执行后才知道算法的效率和容易受到其他因素的影响,一般使用事前估算法。
当一个算法用高级语言实现后,除了机器性能的硬件因素和软件因素,仅考虑算法本身效率高低,依赖于问题的规模。
一个算法是由控制结构(顺序、分支和循环三种)和原操作(指固有数据类型的操作,如n++等)构成的,则算法时间取决于两者的综合效果。
为了便于比较同一问题的不同算法,通常从算法中选取一种对于所研究的问题来说是基本运算的原操作。
算法执行时间大致为基本运算所需的时间与其运算次数(也称为频度)的乘积。
通常把算法中包含基本运算次数的多少称为算法的时间复杂度,也就是说,一个算法的时间复杂度是指该算法的基本运算次数。 算法中基本运算次数T(n)是问题规模n的某个函数f(n),记作: T(n)=O(f(n))。
记号“O”读作“大O”,它表示随问题规模n的增大算法执行时间的增长率和f(n)的增长率相同。
“O”的形式定义为: 若f(n)是正整数n的一个函数,则T(n)=O(f(n))表示存在一个正的常数M,使得当n≥n0时都满足: |T(n)|≤M|f(n)|,也就是只求出T(n)的最高阶,忽略其低阶项和常系数,这样既可简化T(n)的计算,又能比较客观地反映出当n很大时算法的时间性能。
例如,T(n)=3n2-5n+10000=O(n2)
一个没有循环的算法的基本运算次数与问题规模n无关,记作O(1),也称作常数阶。
一个只有一重循环的算法的基本运算次数与问题规模n的增长呈线性增大关系,记作O(n),也称线性阶。
各种不同数量级对应的值存在着如下关系: O(1)<O(log2n)<O(n)<O(nlog2n)<O(n2)<O(n3)<O(2n)<O(n!)
平均复杂度:在所有可能的输入实例以等概率出现的的情况下,算法的期望运行时间与问题规模n的数量级的关系。
例1,分析以下算法的时间复杂度:
void func(int n) {
int i=0,s=0;
while (s<n) {
i++;
s=s+i;
}
}
解:对于while循环语句,设执行的次数为m,i从0开始递增1,直到m为止,有: s=0+1+2+…+(m-1)=m(m-1)/2, 并满足s=m(m-1)/2<n,则有m<根号n,T(n)=O(根号n)。
所以,时间复杂度为O(根号n)。
例2,有平方阶算法:
int i,j, n=100;
for(i=0;i<n;i++)
{
for (j=i;j<n;j++)
printf("123");
}
解:从内层循环开始看,j=i,当i=0时,j循环n次,...当i=n-1时,j循环一次。
所以内层循环总次数为n+(n-1)+(n-2)+...+1=n(n+1)/2,时间复杂度为O(n2)。
例3,有对数阶算法:
int i=1,n=100;
while(i<n)
{
i=i*2;
}
解:首先看到内层语句i=i*2,又因为while循环i<n,循环得到2的i次方<n,求解取对数则为log2n
时间复杂度为O(log2n)。
例4,有如下算法:
void fun(int a[],int n,int k) //数组a共有n个元素
{ int i;
if
4000
(k==n-1)
for (i=0;i<n;i++) //n次
printf("%d\n",a[i]);
else {
for (i=k;i<n;i++) //n-k次
a[i]=a[i]+i*i;
fun(a,n,k+1);
}
} 调用上述算法的语句为fun(a,n,0),求其时间复杂度。
解:设fun(a,n,0)的时间复杂度为T(n),则fun(a,n,k)的执行时间为T1(n,k)
由fun()算法可知: T1(n,k)=n 当k=n-1时 T1(n,k)= (n-k)+T1(n,k+1)
其他情况 则 T(n)=T1(n,0)=n+T1(n,1)=n+(n-1)+T1(n,2) =…=n+(n-1)+…+2+T1(n,n-1) =n+(n-1)+ …+2+n =O(n2)
所以调用fun(a,n,0)的时间复杂度为O(n2)。
三、算法空间复杂度分析
空间复杂度是对一个算法在运行过程中输入数据和辅助变量的所占空间,是临时占用的存储空间大小的量度,一般也作为问题规模n的函数。
以数量级形式给出,记作: S(n) = O(g(n))。
四、数据结构名人
N.wirth,沃思著作:数据结构+算法=程序,他指出:程序就是在数据的某些特定的表示方法和结构的基础上,对抽象算法的具体表述,所以说程序离不开数据结构。
数据结构的概念由CA.R HOARE和N.writh于1966年提出。
五、存储结构对算法的影响
主要在两方面:
1)存储结构的存储能力。如果存储结构存储能力强、存储信息多,算法将会较好设计。反之对于过于简单的存储结构,可能就要设计一套比较复杂的算法。在这一点上,经常体现时间与空间的矛盾,往往存储能力是与所使用的空间大小成正比的。
2)存储结构应与所选择的算法相适应。存储结构是实现算法的基础,也会影响算法的设计,其选择要充分考虑算法的各种操作,应与算法的操作相适应。
数据元素之间的关系有逻辑关系和物理关系,对应的操作有逻辑结构上的操作功能和具体存储结构上的操作实现。
通常把具体存储结构上的操作实现步骤或过程称为算法。
算法有五个重要的特性1)有穷性 2)确定性 3)可行性 4)有输入 5)有输出
算法设计应满足以下几条目标: 1)正确性 2)可使用性 3)可读性 4)健壮性 5)高效率和低存储量需求
二、 算法时间复杂度分析
通常有两种衡量算法效率的方法:事后统计法和事前估算法。但是由于事后统计法必须执行后才知道算法的效率和容易受到其他因素的影响,一般使用事前估算法。
当一个算法用高级语言实现后,除了机器性能的硬件因素和软件因素,仅考虑算法本身效率高低,依赖于问题的规模。
一个算法是由控制结构(顺序、分支和循环三种)和原操作(指固有数据类型的操作,如n++等)构成的,则算法时间取决于两者的综合效果。
为了便于比较同一问题的不同算法,通常从算法中选取一种对于所研究的问题来说是基本运算的原操作。
算法执行时间大致为基本运算所需的时间与其运算次数(也称为频度)的乘积。
通常把算法中包含基本运算次数的多少称为算法的时间复杂度,也就是说,一个算法的时间复杂度是指该算法的基本运算次数。 算法中基本运算次数T(n)是问题规模n的某个函数f(n),记作: T(n)=O(f(n))。
记号“O”读作“大O”,它表示随问题规模n的增大算法执行时间的增长率和f(n)的增长率相同。
“O”的形式定义为: 若f(n)是正整数n的一个函数,则T(n)=O(f(n))表示存在一个正的常数M,使得当n≥n0时都满足: |T(n)|≤M|f(n)|,也就是只求出T(n)的最高阶,忽略其低阶项和常系数,这样既可简化T(n)的计算,又能比较客观地反映出当n很大时算法的时间性能。
例如,T(n)=3n2-5n+10000=O(n2)
一个没有循环的算法的基本运算次数与问题规模n无关,记作O(1),也称作常数阶。
一个只有一重循环的算法的基本运算次数与问题规模n的增长呈线性增大关系,记作O(n),也称线性阶。
各种不同数量级对应的值存在着如下关系: O(1)<O(log2n)<O(n)<O(nlog2n)<O(n2)<O(n3)<O(2n)<O(n!)
平均复杂度:在所有可能的输入实例以等概率出现的的情况下,算法的期望运行时间与问题规模n的数量级的关系。
例1,分析以下算法的时间复杂度:
void func(int n) {
int i=0,s=0;
while (s<n) {
i++;
s=s+i;
}
}
解:对于while循环语句,设执行的次数为m,i从0开始递增1,直到m为止,有: s=0+1+2+…+(m-1)=m(m-1)/2, 并满足s=m(m-1)/2<n,则有m<根号n,T(n)=O(根号n)。
所以,时间复杂度为O(根号n)。
例2,有平方阶算法:
int i,j, n=100;
for(i=0;i<n;i++)
{
for (j=i;j<n;j++)
printf("123");
}
解:从内层循环开始看,j=i,当i=0时,j循环n次,...当i=n-1时,j循环一次。
所以内层循环总次数为n+(n-1)+(n-2)+...+1=n(n+1)/2,时间复杂度为O(n2)。
例3,有对数阶算法:
int i=1,n=100;
while(i<n)
{
i=i*2;
}
解:首先看到内层语句i=i*2,又因为while循环i<n,循环得到2的i次方<n,求解取对数则为log2n
时间复杂度为O(log2n)。
例4,有如下算法:
void fun(int a[],int n,int k) //数组a共有n个元素
{ int i;
if
4000
(k==n-1)
for (i=0;i<n;i++) //n次
printf("%d\n",a[i]);
else {
for (i=k;i<n;i++) //n-k次
a[i]=a[i]+i*i;
fun(a,n,k+1);
}
} 调用上述算法的语句为fun(a,n,0),求其时间复杂度。
解:设fun(a,n,0)的时间复杂度为T(n),则fun(a,n,k)的执行时间为T1(n,k)
由fun()算法可知: T1(n,k)=n 当k=n-1时 T1(n,k)= (n-k)+T1(n,k+1)
其他情况 则 T(n)=T1(n,0)=n+T1(n,1)=n+(n-1)+T1(n,2) =…=n+(n-1)+…+2+T1(n,n-1) =n+(n-1)+ …+2+n =O(n2)
所以调用fun(a,n,0)的时间复杂度为O(n2)。
三、算法空间复杂度分析
空间复杂度是对一个算法在运行过程中输入数据和辅助变量的所占空间,是临时占用的存储空间大小的量度,一般也作为问题规模n的函数。
以数量级形式给出,记作: S(n) = O(g(n))。
四、数据结构名人
N.wirth,沃思著作:数据结构+算法=程序,他指出:程序就是在数据的某些特定的表示方法和结构的基础上,对抽象算法的具体表述,所以说程序离不开数据结构。
数据结构的概念由CA.R HOARE和N.writh于1966年提出。
五、存储结构对算法的影响
主要在两方面:
1)存储结构的存储能力。如果存储结构存储能力强、存储信息多,算法将会较好设计。反之对于过于简单的存储结构,可能就要设计一套比较复杂的算法。在这一点上,经常体现时间与空间的矛盾,往往存储能力是与所使用的空间大小成正比的。
2)存储结构应与所选择的算法相适应。存储结构是实现算法的基础,也会影响算法的设计,其选择要充分考虑算法的各种操作,应与算法的操作相适应。
相关文章推荐
- 迪杰斯特拉(Dijkstra)算法描述及其正确性证明
- AAN算法描述及其实现
- 实验一算法描述及其程序实现
- otsu自适应阈值分割的算法描述和opencv实现,及其在肤色检测中的应用
- otsu自适应阈值分割的算法描述和opencv实现,及其在肤色检测中的应用
- otsu自适应阈值分割的算法描述和opencv实现,及其在肤色检测中的应用
- 数据结构-绪论-算法及其描述
- otsu自适应阈值分割的算法描述和opencv实现,及其在肤色检测中的应用
- 第1周第2节课 算法及其描述、算法分析基础
- otsu自适应阈值分割的算法描述和opencv实现,及其在肤色检测中的应用
- otsu自适应阈值分割的算法描述和opencv实现,及其在肤色检测中的应用
- 第一周第二节课:算法及其描述
- otsu自适应阈值分割的算法描述和opencv实现,及其在肤色检测中的应用[转]
- otsu自适应阈值分割的算法描述和opencv实现,及其在肤色检测中的应用
- PCA算法及其数学原理
- Camshift算法原理及其Opencv实现
- Canny边缘检测算法原理及其VC实现详解(二)
- 求二叉树中任意两结点的最近共同祖先的算法及其证明
- 【随笔】游戏程序开发必知的10大基础实用算法及其讲解
- hdu 4975 最大流及其唯一性判定(有向图环判断算法升级)