1——算法的定义
一个有限指令集
接受一些输入(有些情况 下不需要输入)
产生输入
一定在有限步骤之后终止
每一条指令必须:
有充分明确的目标,不可以有歧义。
计算机能处理的范围之内。
描述应不依赖于任何一种计算机语言以及具体的实现手段。
例1:选择排序算法的伪码描述
void SelectionSort (int List[], int N)
{//将N个整数List[0]...List[N-1]进行非递减排序
for(i=0;i<N;i++)
{
MinPosition = ScanForMin(List,i,N-1);
//从List[i]到List[N-1]中找最小元,并将其位置赋给MinPosition
将未排序部分的最小元换到有序部分的最后位置;
}
}
抽象——
List到底是数组还是链表(虽然看上去是数组)?
Swap用函数还是用宏实现?
2——什么是好算法
空间复杂度S(n)——根据算法写成的程序在执行时占用存储单元的长度。这个长度往往与输入数据的规模有关。空间复杂度过高的算法可能导致使用的内存超限,造成程序非正查岗中断。
时间复杂度T(n)——根据算法写成的程序在执行时耗费时间的长度。这个长度往往也与输入数据的规模有关。时间复杂度过高的低效算法可能导致我们在有生之年都等不到运行结果。
例:
void PrintN(int N)
{
if(N)
{
PrintN(N-1);
printf("%d\n",N);
}
return;
}
此时PrintN(100000)......PrintN(0)
占用空间S(N)=C·N
例:
double f(int n,double a[],double x)
{
int i;
double p=a[0];
for(i=1;i<=n;i++)
p+=(a[i]*pow(x,i));
return p;
}
T(n)=C1·n平方+C2·n
double f(int n,double a[],double x)
{
int i;
double p=a[n];
for(i=n;i>0;i--)
p=a[i-1]+x*p;
return p;
}
T(n)=C·n
在分析一般算法的效率时,我们经常关注下面两种复杂度:
①最坏情况复杂度Tworst(n)
②平均复杂度Tavg(n)
Tavg(n)<Tworst(n)
分析最坏情况复杂度比平均复杂度要多。
3——复杂度的渐进表示法
T(n)=O(f(n))表示存在常数C>0,n0>0使得当n>n0时有T(n)≤C·f(n)(相当于上界)
T(n)=O(g(n))表示存在常数C>0,n0>0使得当n>n0时有T(n)≥C·g(n)(相当于下界)
T(n)=O(h(n))表示存在常数C>0,n0>0使得当n>n0时有T(n)=C·h(n)(既是上界也是下界)
复杂度分析小窍门:
若两段算法分别有复杂度T1(n)=O(f1(n))和T2(n)=O(f2(n)),则:
T1(n)+T2(n)=max(O(f1(n)),O(f2(n)))
T1(n)×T2(n)=O(f1(n)×f2(n))
若T(n)是关于n的k阶多项式,那么T(n)=O(n的k次方)
一个for循环的时间复杂度等于循环次数乘以循环体代码的复杂度
if-else结构的时间复杂度取决于if的条件判断复杂度和两个分枝部分的复杂度,总体复杂度取三者中最大。