大话数据结构 第二章 算法
2.1 开场白
2.2 数据结构与算法的关系
程序设计 = 数据结构+算法
2.3 两种算法的比较
问题:求1+2+3+…+100的和
算法一:
int i, sum = 0, n = 100;
for(i=0;i<100;i++)
{
sum += i;
}
算法二:
利用等差数列求和思想:
int i, sum = 0, n = 100;
sum = (1 + n) * n / 2;
区别:
算法一用了循环,当n很大时,速度会很慢。
2.4 算法的定义
解决特定问题求解步骤的描述,在计算机表现为指令的有限序列,并且每条指令表示一个或者多个操作。
概括为:求解问题的方法。
2.5 算法的特征
2.5.1 输入输出
算法具有另个或者多个输入。
算法至少具有一个输出(问题的解,想要的结果)。
2.5.2 有穷性
算法在执行有限步骤后,自动结束,不会出现无限循环,且每一个步骤在可接受的时间内执行完成(算法是为了解决问题,问题得解决,因此不能无限循环)。
2.5.3 确定性
算法的每一步都具有确定的含义,不会出现二义性。(相同的输入只有一个唯一的结果)
2.5.4 可行性
算法的每一步都是可行的,以为中可以转换为程序上机运行,且能得到正确的结果。
2.6 算法设计的要求
算法不是唯一的。
2.6.1 正确性
算法的正确性是指算法至少应该具有输入输出和加工处理无歧义性,能正确反映问题的需求,能够得到正确的答案。
体现在:
输入输出正确;
正确反映问题的需求;
得到的答案正确;
2.6.2 可读性
算法设计的另一个目的为了便于阅读,理解和交流。
是算法好坏的很重要的标志。
2.6.3 健壮性
当输入数据不合法时,算法也能做出相应的处理,而不是产生异常或莫名其妙的结果。
2.6.4 时间效率高和存储量低
好的算法应该在时间复杂度(效率高)和空间复杂度(存储量低)有着很好的表现。
2.7 算法效率的度量方法
2.7.1 事后统计方法
通过设计好的测试程序和数据,利用计算机计时器对不同的算法编制的程序的运行时间进行比较。— 定量
劣势:
- 需要实现实现算法,对算法的好坏不能估计,因此,可能会耗费人力和时间产生较坏的算法。
- 算法的运行时间依赖于计算机硬件和软件,有时候会掩盖算法本身的优劣。
- 算法的测试数据设计困难,优秀的算法在较小的数据集可能体现不出来,在较大的数据集中有明显的优势。
2.7.2 事前分析估计方法
在计算机程序编译前,依据统计方法对算法进行估计。 – 定性
一个算法的运行时间由执行代码行数决定。执行代码行数与输入规模有关。
比较下面两种算法:
算法一:
int i, sum = 0, n = 100; /* 执行一次 */
for(i = 1; i < = n; i++){ /* 执行n+1 */
sum += i; /* 执行n次 */
}
算法二:
int i, sum = 0, n = 100; /* 执行一次 */
sum = (1 + n) * n / 2; /* 执行一次 */
算法一执行行数为2n+2, 将随着输入规模n的增大而增大;
算法二执行行数不管n为多少,始终为2。
2.8 函数的渐进增长
给定两个函数f(n)和g(n),如果存在一个整数N(N>0),使得对于n>N,f(n)>g(n),那么我们就说f(n)的增长渐进快于g(n)。
说明:
- 在n<N时,f(n)<=g(n)。即好的算法在较小的数据集上的表现可能不如坏的算法。
- n>N时, 说明数据量越大,好的算法优势就会越明显,因此,可以直接考虑一个很大的值时,此时,上述2.7节提及的执行行数中的常数可以忽略不计。
- 定性比较两种算法时,当两种算法的执行行数f(n)处于不同的高阶函数,如8n, 2n^2,等,此时由于n很大,可以直接忽略高阶项前面相乘的系数;当两种算法的执行行数处于相同高阶函数时,如2n, 8n等,此时则需要考虑高阶项前面的系数。
2.9 算法时间复杂度
2.9.1 定义
在(定性)分析算法时,算法中语句执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级。
算法的时间复杂度,也就是算法的时间度量(即上述说的执行时间),记作:T(n) = O(f(n))。该公式表示:随着问题规模n的增大,算法执行时间的增长率和f(n)[执行次数]的增长率相同。
说明:
- 使用大写的O()体现时间复杂度,称之为大O记法;常数阶O(1), 线性阶O(n), 平方阶(n^2)
- 随着n的增大,T(n)增长最慢的算法为最优的算法。
2.9.2 推导大O阶的方法
step1: 表明每行代码执行的次数
step2: 用常数1替换所有加法常数
step3: 保留最高阶项
step4: 如果最高阶项不为1,则将最高阶项前的系数变为1
step5: 最高阶项则为最终的大O阶
注意:
当比较两种算法时,如果最高阶项处于同一阶,则需要考虑最高阶项前的系数。
2.10 常见的时间复杂度
2.11 最坏情况和平均情况
最坏情况:运行结果最差的时候;通常,我们提到的运行时间都是最坏的情况。
平均情况:期望的运行时间
2.12 算法的空间复杂度
算法所需要的存储空间。
记作S(n) = O(f(n))。
重点考察时间复杂度。
2.13 总结回顾
- 算法的定义,特征,设计要求
- 算法的度量方法,时间复杂度和空降复杂度。