第一节 算法分析 - Analysis of algorithm
算法分析:是关于计算机程序性能和资源利用的研究
1.算法分析的主要内容是性能,什么比性能更重要呢?当然有,比如正确性、简洁性、可维护性、可扩展性、健壮性、安全性等等
但是如果算法和性能都不重要 为什么要学习呢?
- 1.性能的好坏直接决定可行性与不可行性。算法能够将不可行变成可行。
- 2.算法是一种描述程序行为的语言。算法如同货币一样 ,或许我们更需要水,食物,房子等。但需要有货币才能买下这些商品。
- 3.性能是确保良好的用户体验的前提 也是安全的保障。算法分析中的“性能”就相当于“钱”,你可以用“性能”来换取其他东西,比如安全性,稳定性等等。
排序问题
例1.输入:一组序列<a1,a2...an> 按照需求重新排列后作为输出:<a1',a2'...an'>
使得a1'<=a2'<=...<=an'
1.插入排序
sort A[1..n] 长度为n的一个序列
插入排序:(伪代码)
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
设置外部循环 j为从2到n递增 内部循环开始于j-1并递减至0
插入式排序属于内部排序法,是对于欲排序的元素以插入的方式找寻该元素的适当位置
插入排序 (Insertion Sorting) 的基本思想是:把 n 个待排序的元素看成为一个有序表和一
个无序表,开始有序表只包含一个元素,无序表中包含有 n-1 个元素,排序过程中每次从
无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入
到有序表中的适当位置,使之成为新的有序表。
插入排序算法的实现
public class Demo01 {
/**
* 插入式排序属于内部排序法,是对于欲排序的元素以插入的方式找寻该元素的适当位置,
以达到排序的目的。
插入式排序法又可分为 3 种:
1、插入排序法 (Insertion Sorting)
2、谢耳排序法 (Shell Sorting)( 欧洲人员喜欢使用 )
3、二叉树排序法 (Binary-tree Sorting)
插入排序 (Insertion Sorting) 的基本思想是:把 n 个待排序的元素看成为一个有序表和一
个无序表,开始有序表只包含一个元素,无序表中包含有 n-1 个元素,排序过程中每次从
无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入
到有序表中的适当位置,使之成为新的有序表。
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int arr[]={8,2,4,9,3,6};
InsertSort i1=new InsertSort();
i1.sort(arr);
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+"\t");
}
}
}
class InsertSort{
//插入式排序法
public void sort(int arr[]){
for(int i=1;i<arr.length;i++){
int insertVal=arr[i];
//insertVal准备和前一个数比较
int index=i-1;
while(index>=0&&insertVal<arr[index]){
arr[index+1]=arr[index];
//让index向前移动
index--;
}
// 将 insertVal 插入到适当位置
arr[index+1]=insertVal;
}
}
}
插入排序的最坏情况运行时间
取决于运行的计算机
比较算法时 通常比较的是其相对速度(两个算法在同一台机器上)
算法的大局观 渐近分析
基本思路:1.忽略掉依赖机器的常量 2.不去检查实际的运行时间,而是关注运行时间如何增长
θ符号 一个公式 弃去它的低阶项 并忽略前面的常数因子
例如:3n3+90n2-5n+6046=θ(n3)
当n趋向于无穷大时 θ(n2) 总会优于θ(n3) 的算法
T(n)=j从2到n θ(j)=θ(n2) 算术级数
对于比较大的n运行时间不快
归并排序 A[1..n]
1.如果n=1 done
2.递归算法
递归的对A[1..n/2] (n/2向上取整) 以及A[n/2+1..n] (n/2向上取整) 排序
3.吧排好序的两个表归并
归并子序列
归并排序的递归表达式(通常省略常数的基本情形)
运行成本几何(递归树方法)T(n)=2T(n/2)+cn 用cn显示函数替换掉了隐式的θ(n)
构造递归树的方法
当n足够大时 归并排序优于插入排序
算法的运行时间
- 取决于输入值本身(顺序逆序)
- 取决于输入规模(元素个数 处理输入规模方式:将输入的规模参数化以后,把运行时间看做待排列数据规模的函数)
- 运行时间的上限(运行时间是不会超过某个特定量的 代表对用户的承诺)
- 最坏情况分析
- T(n)定义为输入规模为n的最长运行时间(若我们得不到最大值,T(n)在某种意义上只能算一种相关性,而不能算函数)
- 平均情况分析
- T(n)为输入规模n之下所有可能输入的期望时间(加权平均,需要一个有关输入的统计分布的假设)
- 最好情况分析
- 假象