算法是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或多个操作。
算法五个基本特征:输入,输出,有穷性,确定性和可行性。
1.输入:算法具有零个或多个输入。
2.输出:算法至少有一个或多个输出。算法是一定要输出的,输出的形式可以是打印形式输出,也可以是返回一个值或多个值等。
3.有穷性:指算法在执行有限的步骤之后,自动结束而不会出现无限循环,并且每一个步骤在可接受的时间内完成。
4.确定性:算法的每一个步骤都有确定的含义,不会出现二义性。算法在一定条件下,只有一条执行路径,相同的输入只能有唯一的输出结果。算法的每个步骤都应该被精确定义而无歧义。
5.可行性:算法的每一步都必须是可行的,也就是说,每一步都能够通过执行有限次数完成。
算法设计的要求:
1.正确性:没有语法错误,对于合法输入能够产生满足要求的输出,对于非法输入能够产生满足规格的说明,对于故意刁难的测试输入都有满足要求的输出结果。
2.可读性:便于阅读、理解和交流。
3.健壮性:当输入数据不合法时,算法也能做出相关处理,而不是产生异常、崩溃或莫名其妙的结果。
4.时间效率高和存储量低。
判断一个算法的效率:函数中的常数和其他次要项常常可以忽略,而更应该关注主项(最高项)的阶数。
算法时间复杂度
1.用常数1取代运行时间中的所有加法常数。
2.在修改后的运行次数函数中,只保留最高阶项。
3.如果最高阶存在且不是1,则去掉去这个项相乘的常数,得到的最后结果就是大O阶。
eg:
1.常数阶:不是有多少条语句就有多少条,一般没有循环嵌套均为O(1)。
2.线性阶:一般含有非嵌套循环涉及线性阶,线性阶就是随着问题规模n的扩大,对应计算次数呈直线循环。如
int i, n=100,sum=10;
for(i=0;i<n;i++)
{
sum=sum+i;
}
循环体中的代码需要执行n次,则它的循环时间复杂度为O(n).
3.平方阶:int i,j,n=100;
for(i=0;i<n;i++)
{for(j=0;j<n;j++)
{printf("hello world\n");
}
}
这段代码的时间复杂度为O(n^2)
4.若2中的代码二层嵌套中条件语句改为j=i,则执行次数应该是n(n+1)/2=n^2/2+n/2
只保留最高项,所以n/2这项去掉。
去掉与最高项相乘的常数,最终得O(n^2)。
5.对数阶:
int i=1,n=100;
while(i<n)
{i=i*2;
}
假设有x个2相乘后大于或等于n,则会退出循环。于是由2^x=n得到x=log(2)n,所以这个循环的时间复杂度为O(logn)。