《大话数据结构》2

第二章 算法

算法:算法是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每次指令表示一个或多个操作
算法具有五个特点:输入、输出、有穷性、确定性和可行性

2.5.1 输入输出

算法具有零个或多个输入
算法至少有一个或多个输出

2.5.2 有穷性

有穷性:指算法在执行有限的步骤之后,自动结束而不会出现无限性循环,并且一个步骤在可接受的时间内完成

2.5.3 确定性

确定性:算法的每一步骤都具有确定的含义,不会出现二义性

2.5.4 可行性

可行性:算法的每一步都必须是可行的,也就是说,每一步都能够通过执行有限次数完成

2.6.1 正确性

正确性:算法的正确性是指算法至少应该具有输入、输出和加工处理无歧义性,能正确反映问题的需求,能够得到问题的正确答案

2.6.2 可读性

可读性:算法设计的另一目的是为了便于阅读、理解和交流

2.6.3 健壮性

健壮性:当输入数据不合法时,算法也能够做出相关处理,而不是产生异常或莫名其妙的结果

2.6.4 时间效率高和存储量低

设计算法应该尽量满足时间效率高和存储量低的需求

事后统计法

事后统计法:这种方法主要是通过设计好的测试程序和数据,利用计算机计时器对不同算法编制的程序的程序的运行时间进行比较,从而确定算法效率的高低

2.7.2 事前分析估计方法(P24)

事前分析估计方法:在计算机程序便之前,依据统计方法对算法进行估算
测定运行时间最可靠的方法就是计算对运行时间有消耗的基本操作的执行次数,运行时间与这个计数成正比
一个程序的运行时间,依赖与算法的好坏和问题的输入规模(输入量的多少)
最终,在分析程序的运行时间时,最重要的是把程序看成是独立于程序设计语言的算法或一系列步骤
分析一个算法的运行时间时,重要的是把基本操作的数量与输入规模关联起来,即基本操作的数量必须表示成输入规模的函数

2.8 函数的渐近增长

函数的渐近增长:给定两个函数 f ( n ) f(n) f(n) g ( n ) g(n) g(n),如果存在一个整数N,使得对于所有的n>N, f ( n ) f(n) f(n)总是比 g ( n ) g(n) g(n)大,那么,我们说 f ( n ) f(n) f(n)的增长渐进快于 g ( n ) g(n) g(n)

可以忽略函数的部分(P26)
可以忽略加法常数
与最高次项相乘的常数并不重要
最高此项的指数大的,函数随着n的增长,结果也会增长更快

判断一个算法的效率时,函数中的常数和其他次要项常数可以忽略,而更应该关注主项(最高阶项)的阶数

某个算法,随着n的增长,他会越来越优于另一算法或者越来越差于另一算法。事前估计方法的理论依据,通过算法时间复杂度来估算改时间效率

2.9.1 算法时间复杂度的定义

在进行算法分析时,语句总的执行次数 T ( n ) T(n) T(n)是关于问题规模n的函数,进而分析 T ( n ) T(n) T(n)随n的变化情况并确定 T ( n ) T(n) T(n)的数量级。算法的时间复杂度,也就是算法的时间量度,记作 T ( n ) = O ( f ( n ) ) T(n)=O(f(n)) T(n)O(f(n))。它表示随问题规模n的增大,算法执行时间的增长率和 f ( n ) f(n) f(n)的增长率相同,称作算法的渐进时间复杂度,简称为时间复杂度。其中 f ( n ) f(n) f(n)是问题规模n的某个函数

用大写O来体现算法时间复杂度的记法,称为大O记法
一般情况下,随着n的增大,T(n)增长最慢的算法为最优算法

2.9.2 推导大O阶方法

推导大O阶
(1) 用常数1取代运行时间的所有加法常数
(2) 再修改后的运行次数函数中,只保留最高阶项
(3) 如果最高级项存在且其系数不是1,则去除与这个项相乘的系数。得到的结果就是大O阶

2.9.3 常数阶

就是执行次数可数的称为常数阶(个人理解)
注意:不管常数是多少,我们都记作O(1),而不是O(3)、O(12)等其他任何数字,这是初学者常犯的错误

2.9.4 线性阶

分析算法的复杂度,关键就是要分析循环结构的运行情况
下面的代码,它的循环的时间复杂度为O(n),因为循环体中的代码需要执行n次

int i;
for (i = 0; i < n; i++)
{
	/* 时间复杂度为O(1)的程序步骤序列 */
}
2.9.5 对数阶
int count = 1;
while (count < n)
{
	count = count * 2/* 时间复杂度为O(1)的程序步骤序列 */
} 

数学计算,不解释了
2 x = n 2^x=n 2x=n 得到 x = l o g 2 n x=log_2n x=log2n 。所以这个循环的时间复杂度为 O ( l o g 2 n ) O(log_2n) O(log2n)

2.9.6 平方阶
int i,j;
for (i = 0;i < n;i++)
{
	for (j = i;j < n;j++)
	{
		/* 时间复杂度为O(1)的程序步骤序列 *、
	}
}		 

i = 0 内循环 n 次。i = 1 内循环 n-1 次,以此类推
n + ( n − 1 ) + . . . + 1 = n ( n + 1 ) 2 = n 2 2 + n 2 n + (n-1) +. .. + 1 = \frac{n(n+1)}{2}=\frac{n^2} {2} + \frac{n}{2} n+(n1)+...+1=2n(n+1)=2n2+2n
时间复杂度为O( n 2 n^2 n2)

理解大O阶推到不算难,难的是对数列的一些相关运算,这更多的是考察数学知识和能力

2.10 常见的时间复杂度
执行次数非正式术语
12 12 12 O ( 1 ) O(1) O(1)常数阶
2 n + 3 2n+3 2n+3 O ( n ) O(n) O(n)线性阶
3 n 2 + 2 n + 1 3n^2+2n+1 3n2+2n+1 O ( n 2 ) O(n^2) O(n2)平方阶
5 l o g 2 n + 20 5log_2n+20 5log2n+20 O ( l o g n ) O(logn) O(logn)对数阶
2 n + 3 n l o g 2 n + 19 2n+3nlog_2n+19 2n+3nlog2n+19 O ( n l o g n ) O(nlogn) O(nlogn) n l o g n nlogn nlogn
6 n 3 + 2 n 2 + 3 n + 4 6n^3+2n^2+3n+4 6n3+2n2+3n+4 O ( n 3 ) O(n^3) O(n3)立方阶
2 n 2^n 2n O ( 2 n ) O(2^n) O(2n)指数阶

O ( 1 ) O(1) O(1)< O ( l o g n ) O(logn) O(logn)< O ( n ) O(n) O(n)< O ( n l o g n ) O(nlogn) O(nlogn)< O ( n 2 ) O(n^2) O(n2)< O ( n 3 ) O(n^3) O(n3)< O ( 2 n ) O(2^n) O(2n)< O ( n ! ) O(n!) O(n!)< O ( n 2 ) O(n^2) O(n2)

2.11 最坏情况与平均情况

最坏情况运行时间是一种保证,那就是运行时间不能再坏了。在应用中,这是一种最重要的需求。通常,除非特别指定,我们提到的运行时间都是最坏情况的运行时间
平均运行时间是所有情况中最有意义的,因为他是期望的运行时间

计算所有情况的平均值,这种时间复杂度的计算方法称为平均时间复杂度
计算最坏情况下的时间复杂度,这种方法称为最坏时间复杂度

一般在没有特殊说明的情况下,都是指最坏时间复杂度

2.12 算法空间复杂度 (P33)

用空间换取时间
算法的空间复杂度通过计算算法所需的存储空间实现,算法空间复杂度的计算公式记作: S ( n ) = O ( f ( n ) ) S(n)=O(f(n)) S(n)=O(f(n)),其中,n 为问题的规模, f ( n ) f(n) f(n)为语句关于 n 所占存储空间的函数
时间复杂度指运行时间的需求
空间复杂度指空间需求
当不用限定词地使用“复杂度”时,通常都是指时间复杂度

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值