第二章算法
文章目录
前言
算法内容过多,在大学也是作为一门课程单独讲,这里谈及的算法只为了更好的理解数据结构
一、算法定义
概念:解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且为每条指令表示一个或多个操作
二、算法特性
2.1 输入输出
概念:算法输入>=0;算法输出>=1
2.1 有穷性
概念:算法在执行有限的步骤之后,自动结束且不会出现无限循环,并且每一个步骤在可接受的时间内完成。
2.1 确定性
概念:算法的每一步骤都具有确定的含义,不会出现二义性。也就是说算法在一定条件下,只有一条执行路径,相同的输入如只能有一个唯一的输出结果
2.1 可行性
概念:算法的每一步都必须是可行的,每一步都能够通过执行有限次数完成
三、算法设计的要求
3.1 正确性
概念:算法至少应该具有输入、输出和加工处理无歧义性、能正确反应问题的需求、能够得到问题的正确答案。

3.2 可读性
概念:便于其他人阅读、理解和交流
3.3 健壮性
概念:当输入数据不合法时,算法也能做出相关处理,而不是产生异常
3.4 时间效率高和存储量低
四、算法效率的度量方法
4.1 事后统计方法
概念:通过设计好的测试程序和数据,利用计算机计时器对不同算法编程的程序运行时间进行比较,从而确定算法效率高低
缺点:
- 必须实现编译好程序,无论程序好坏都已经耗费大量时间精力
- 依赖计算机软硬件等环境因素,可能会掩盖算法的优缺点:就像一个兼容性不太好的页面在Chrome完美运行和在IE上错误频发一样
- 需要设计能体现算法效率的测试数据:.拿一个高效的算法和低效的算法去测试10个数的排序很难看出有啥区别
4.2 事前分析估算方法
概念:在计算机程序编制前,依据统计方法对算法进行估算(不考虑其他因素,只计算算法的基本操作的执行次数)
影响程序运行效率的因素:
- 算法采用的策略、方法(算法好坏的根本)
- 编译产生的代码质量(软件支持)
- 问题的输入规模
- 机器执行指令的速度(硬件支持)
算法一
int i, sum = 0, n = 100; /*执行一次*/
for (i = 1;i <= n; i++){ /*执行n+1次*/
sum = sum + i; /*执行n次*/
}
printf("%d", sum); /*执行一次*/
共执行了2n + 3次
算法二
sum = 0, n = 100; /*执行一次*/
sum = (1 + n) * n / 2; /*执行一次*/
printf("%d", sum); /*执行一次*/
共执行3次
五、函数的渐进增长
如下图,在10次之内时,0.1 * x ^ 2的算法效率自然是低于 x;但若是大于10,则明显是x更效率;
而 x ^ 2 + x + 1和 x ^ 2,在当x特别特别大的时候,例如10000000,那么x+1所带来的差距就显得可以忽略不计;
所以在不精确判断俩算法效率且大批数据的情况下,可以直接通过判断最高阶的差距来区分

由此,某个算法,随着n的增大,它会越来越优(差)于另一个算法,通过算法时间复杂度来估算算法时间效率
六、算法时间复杂度
关于语句的总执行次数与相关问题规模的关系可以用函数表述:T(n) = O(fn(n)) ;使用大写O()来体现算法时间复杂度的记法被称为大O记法。随着n增大,T(n)增长最慢的算法一般为最优算法。
- 常数阶O(1):执行次数恒定,不随n变化而增大
- 线性阶O(n):常见的就是for循环遍历n次
- 平方阶O(n²):常见的是循环嵌套
int i, j;
for (i = 0; i <= n; i++){
for (j = 0; j <= n; j++){
//do something
}
}
开头定义就忽略吧,共执行了n²次
int i, j;
for (i = 0; i <= n; i++){
for (j = i; j <= n; j++){
//do something
}
}
则共执行了 n * (n + 1) / 2 次
6.1 常见的时间复杂度
| 耗费时间排名(从低到高) | 阶 | 非正式用语 |
|---|---|---|
| 1 | O(1) | 常数阶 |
| 2 | O(logn) | 对数阶 |
| 3 | O(n) | 线性阶 |
| 4 | O(n * logn) | nlogn阶 |
| 5 | O(n ^ 2) | 平方阶 |
| 6 | O(n ^ 3) | 立方阶 |
| 7 | O(2 ^ n) | 指数阶 |
| 8 | O(n!) | 阶乘阶 |
| 9 | O(n ^ n) | 幂次方阶 |
6.2 最坏情况和平均情况
最坏情况运行时间:保证运行时间不会比这个更坏了,一般没有特殊说明的情况下,说的运行时间指的都是这个
平均情况运行时间:期望的运行时间
七、算法空间复杂度
利用空间存储合适的计算结果或数据换取一部分计算时间,例如多次判断一组年份是否是闰年,需要通过计算得到是否是闰年的结果,如果提前准备一个2050位的数组,对应下标即为年份,闰年值则为1,否则为0,那么该算法空间复杂度则为2050个0或1.
总结和预告
该系列为阅读程杰老师的《大话数据结构》的知识整理和自我归纳,清华大学出版社
下一章,线性表
本文介绍了算法的定义、特性,强调了正确性、可读性和健壮性的设计要求。讨论了算法效率的度量方法,包括事后统计和事前分析估算,并详细阐述了时间复杂度和空间复杂度的概念。

580

被折叠的 条评论
为什么被折叠?



