《算法导论》网易公开课地址
性能的重要
可拓展性,安全等似乎比性能更为重要,但性能像底部的货币,程序以性能为基础,没有性能就没有一切。特别当你研发新产品时,性能更为重要
插入法排序
sorts A[1~n]
pseudocode(伪代码)
for j<-2 to n
do key <- A[j]
i<-j-1
while i>0 and A[i]>key
do A[i+1]<-A[i]
i<-i-1
A[i+1]<-key
注意这里的数组下标是从1开始
下面用c++实现
#include<iostream>
using namespace std;
void main()
{
int A[8]={8,3,5,9,6,5,2,0},i,j,key;
for(j=1;j<8;j++)
{
key=A[j];
i=j-1;
while(i>=0&&A[i]>key)
{
A[i+1]=A[i];
i--;
}
A[i+1]=key;
}
cout<<"the consequence is "<<endl;
for(i=0;i<8;i++)
{
cout<<A[i]<<endl;
}
}
因为c/c++中数组下标从0开始,所以有小改动。
插入法什么意思?
首先选择一个值为key值(从第二个数起选择),然后向前去寻找它应该在的位置。
当A[i]是比key大(从小到大排序),说明key至少在A[i]前面,此时把A[i]往后挪,不断重复(第一次挪会导致key原本的位置被占)。当发现A[i]小于等于key,就把key放到A[i]的后一个。
拿一组数据:8,2,4,9,3
首先选取2为key,往前比较,发现8比2大,又是第一个位置,所以:
2,8,4,9,3
接着4为key值,往前比较,发现8比4大,2又小于4,所以
2,4,8,9,3
9为key值,8不比9大,所以9在原位
2,4,8,9,3
3为key值,9比3大,所以
2,4,8,9,9
3继续往前比,8比3大,所以
2,4,8,8,9
继续
2,3,4,8,9
完成,相当于3直接插入2与4之间,在寻找位置插入过程中key可能在原数组中是没有的。
可以发现,新选一个key时,这个数以前的数组是已经排好序的
running time
- 输入(input),如果输入的数越接近排序好的结果,算法要做的越少
- 数据规模(input size)
- 上限(upper bounds)知道最少会运行的时间用处不大
- worst case(usually),只关注最大值(max time)
- average case (sometimes),期望时间(expected time)
- best case(bogus),不可能发生
插入法运算时间
- depends on computer
- relative speed 不同算法在同一台机器的运算快慢
- absolute speed
asymptotic analysis 渐近分析
- 忽略依赖机器的常量
- 关注运行时间的增长
asymptomatic notation 渐近符号
θ ,舍弃低阶项,并忽略常数。例如 3n3+90n2−5n+6064 ,就等于 θ(n3)
归并排序(merge sort)
sort A[1~n]
1. if n=1 done 如果只有一个数,肯定已经排好序
2. 递归地(recursively)排序A[1~
n2
]和A[
n2
~n],
n2
向上取整。
3. 归并(merge)两个表
归并merge
现在有两张表(list):
20,13,7,2
12,11,9,1
先比较两个表各自最小的数,把1拿出来,于是
20,13,7,2
12,11,9
接着比较剩余部分,两个表中最小的是2,再把2拿出来,于是
20,13,7
12,11,9
而结果部分已经有
1,2
重复,继续比较两个表中各自最小的数把小的那个拿出来
归并时间 T(n)=θ(n) ,线性时间
总的归并排序时间 T(n)=2T(n2)+θ(n) ,n>1