1、算法(Algorithm) 定义:
- 一个有限指令集
- 接受一些输入(有些情况下不需要输入)
- 产生输出
- 一定在有限步骤后终止
- 每一条指令必须:有充分明确的目标,不可以有歧义;计算机能处理的范围之内
2、选择排序算法的伪码描述
伪码的特点就是很抽象,传数组或者链表都可以,
自定义的swap函数也可以不用而用宏。
3、什么是时间复杂度和空间复杂度?
1、
空间复杂度S(n)
—— 根据算法写成的程序在执行时
占用存储单元的长度
。这个长度往往与输入数据的规模有关。空间复杂度越高的算法可能导致使用的内存超限,造成程序非正常中断。
2、
时间复杂度T(n)
—— 根据算法写成的程序在执行时
耗费时间的长度
。这个长度往往也是与输入数据的规模有关。时间复杂度过高的低效算法可能导致我们在有生之年都等不到运行结果。
4、案例1 了解空间复杂度
void PrintN ( int N ) ## 一个递归函数
{ if ( N ) {
PrintN ( N - 1 ); ## 每执行一次调用一次该函数,每一次函数调用都占用一个内存空间
Printf(" %d\n ", N );
}
return; ## 自然而然它的空间复杂度为:S(N) = C·N
}
5、案例2 了解时间复杂度
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;
}
上述时间复杂度是多少呢?
pow指的是x的 i 次幂方,所以for里面做了 i 次乘法,然后算上for循环,总共做的乘法是:(1+2+····+n) = (n^2+n)/2 次乘法
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;
}
for里只做了一次乘法,上述例子做了 n次乘法 。即
6、分析一般算法效率时,常关注下面两种复杂度
1、最坏情况复杂度
2、平均复杂度
7、复杂度的渐进表示法
第一种:表示存在常数C和一个n0,使得当n大于等于n0的时候,f(n)是T(n)的一个上界。简单地说,O(f(n))就表示f(n)是T(n)的某种上界。
第二种:g(n) 是就是 T(n)的某种下界
第三种:表示大O和大
是同时成立的,也就是说 h(n) 既是上界也是下界。
注意:一个函数的上界和下界其实不是唯一的,可以有无穷多个。比如说一个算法的复杂度是n的常数倍,我们可以把它写成 O(n)的,也 可以写成是 O(n^2) 的,甚至是O(n^3) 的。。。下界也是一样。但是呢,太大的上界和太小的下界,对我们分析一个算法的效率而言,是没有什么帮助的。分析算法时,总归是希望不管是上界还是下界,都尽可能地跟它的真实情况贴得越近越好。所以我们在写上界或下界时一般是取我们能找到的、
最小的上界、最大的下界
。
8、常用函数如 log n、n、n^2、n ! 随着n的增大其值的变化图
9、复杂度计算式的小技巧
1、若两段算法分别是有复杂度T1(n) = O(f1(n)) 和 T2(n) = O(f2(n)) 则:
2、若 T(n) 是关于n的k阶多项式,那么
3、已给 for 循环的时间复杂度等于循环次数乘以循环体代码的复杂度
4、if-else 结构的复杂度取决于 if 的条件判断复杂度和两个分支部分的复杂度,总体复杂度取三者中最大。
参考:《数据结构》陈越、何钦铭