算法效率的衡量方法和准则——时间复杂度、空间复杂度

一、衡量算法效率的方法(通常有两种)
1.事后统计法
衡量算法效率最简单的一个办法就是把算法变成一个程序,然后再机器上执行,然后计时,这就是事后统计法。
这样显然有一些缺点:
(1)必须到机器上去计算,而且这个计算不只是一次,我们要用多组数据对其进行重复的运算,然后得到一个统计的结果,那么你要算上机器的时间。
(2)肯定会有一些其他因素掩盖算法的本质。

2.事前分析估算法
通常比较算法好坏,都是在设计算法的时候就应该知道它的效率,这就是事前分析估算法。

说明: 要比较两个算法,实际上在设计的时候就做着工作来衡量它们的效率,因此更常用的方法是事前分析估算法。

二、怎么样估算算法的执行时间
【与算法执行时间相关的因素】
1.算法选用的策略
不同的策略选用的算法是不同的,它的执行时间也是不同的。
2.问题的规模
问题的规模不一样,算法的执行时间当然不一样。
例如:两个矩阵相乘,是10×10的,还是10000×10000的,同样一个算法,执行的时间确实不同的。
3.编写程序的语言
使用高级语言编写的程序比汇编语言编写的程序的执行时间要长。
4.编译程序产生的机器代码的质量
对于同一种高级语言,使用的编译器不同,编译出来的机器代码的质量也会不同。计算机最终执行的是机器代码,机器代码质量不同,算法变成程序后的执行时间也就不同。
5.计算机执行指令的速度
机器的速度不一样,执行的时间也是不一样的 。
例如:一个大型机和一个小型机显然是不一样的。

说明: 后面的三个因素是与计算机的硬件和软件相关的,跟我们设计算法的时候是无关的,所以在设计算法的时候就不再考虑这三个因素。所以,我们考虑算法执行的时间,取决于算法选用的策略和问题的规模,也就是说,一个算法的执行时间是问题规模的的一个函数

三、(渐进)时间复杂度
假如,随着问题规模n的增长,算法执行时间的增长率和 f ( n ) f(n) f(n)的增长率相同,则可记作: T ( n ) = O ( f ( n ) ) T(n)=O(f(n)) T(n)=O(f(n)),称 T ( n ) T(n) T(n)为算法的(渐进)时间复杂度。
T ( n ) = O ( f ( n ) ) T(n)=O(f(n)) T(n)=O(f(n))表明:算法的执行时间 T ( n ) T(n) T(n),它随着问题规模增大而增大的函数的趋势是和 f ( n ) f(n) f(n)这个函数的趋势是相同的,我们称算法的时间和 f ( n ) f(n) f(n)这个函数是成正比的,或者说,这个算法的时间是和 f ( n ) f(n) f(n)这样一个函数的数量级的。

四、如何估算算法的时间复杂度
任何一个算法都是由控制结构和若干个原操作构成的,这里的原操作本来指的是计算机执行的基本指令,但是当我们用伪码语言或者程序语言描述算法的时候,就将固有数据类型的操作看做是原操作,即算法 = 控制结构 + 原操作(固有数据类型的操作)
时间复杂度考虑的是: 随着问题规模n的增长而增长,时间复杂度是一种趋势。一个算法中有很多的原操作,既然我们考虑的是变化的趋势,那么就不必考虑所有的原操作,而只需要在所有的原操作中选取一种所谓基本操作的原操作就行了。这个基本操作的原操作,对于研究的问题来说,它是在所有的原操作中起决定作用的,那么就以该基本操作在算法中重复执行的次数作为算法执行时间的衡量准则
说明:算法的执行时间 = ∑原操作(i)的执行次数 × 原操作(i)的执行时间,其中,原操作(i)的执行时间,对于不同的算法来说,它都是一个定值。因此,在估计算法的时候,往往都会把它忽略掉,也就是说,算法的执行时间与原操作的执行次数之和成正比。

例一、两矩阵相乘

for (i = 1; i <= n; i++)
		for (j = 1; j <= n; j++) 
		{
			c[i][j] = 0;
			for (k = 1; k <= n; k++)
				c[i][j] += a[i, k] * b[k][j];
		}

这个算法的控制结构是一个三重循环,这里的原操作有赋值、有相加、有相乘。显然,乘法操作是这个算法的基本操作,那么可以用乘法操作执行的次数作为该算法时间复杂度的衡量标准。乘法操作在这个三重循环之内,外循环n次,第二重n次,第三重n次,因此这个乘法操作执行的次数为n3,整个算法的执行时间与n3成正比,则这个算法的时间复杂度为: O O O(n3)。

例二、选择排序

void select_sort(int a[], int n)
	{
		//将a中整数序列重新排列成自小到大有序的整数序列
		for (i = 0; i < n - 1; i++)
		{
			j = i;
			for (k = i + 1; k < n; k++)
				if (a[k] < a[j]) j = k;
			if(j!=i) a[j]←→a[j]
		}
	}//选择排序

这个算法的控制结构是两重循环,原操作有赋值,有比较,有交换。显然,基本操作取比较操作。比较操作在两重循环以内,外层循环n次(实际上是n-1次,但是为了方便,可记作n次),内层循环的次数随着i的变化而变化,依次为n-1,n-2,…,1,总次数为等差数列之和,等于 n ( n − 1 ) 2 \frac{n(n-1)}{2} 2n(n1),即 1 2 n 2 − 1 2 n \frac{1}{2}{n^2}-\frac{1}{2}{n} 21n221n。所以,算法的执行时间与 1 2 n 2 − 1 2 n \frac{1}{2}{n^2}-\frac{1}{2}{n} 21n221n成正比,当然与n2成正比,时间复杂度为 O O O(n2)。

上面两个例子有两个共同的特点:
1、一般情况下,算法的基本操作都是在最深层的循环语句中。假如称语句的执行次数为语句的频度,那么在估算算法的时候也可以计算最深层循环中语句的频度,以这个语句频度的函数作为该算法的时间复杂度。
2、算法的效率与输入数据无关。它只是问题规模的函数,无论输入的数据是什么样的,按问题规模的大小,每一步操作都需要进行。但有的算法不是这样的。

例三、冒泡排序

void bubble_sort(int a[], n)
{
	//将a中整数序列重新排列成从小到大的有序的整数序列
	for (i = n - 1, change = true; i > = 1 && change; i--)
	{
		change = false;
		for (j = 0; j < i; j++)
		{
			if (a[j] > a[j + 1])
			{
				a[j]←→ a[j + 1];
				change = ture;
			}
		}
	}
}//bubble_sort

外循环次数取决于 i i i和change,如果一开始的整数序列为[8,7,6,5,4,3,2,1],显然,这个外循环需要进行n-1次;而一开始的整数序列为[1,2,3,4,5,6,7,8,],那么这个外循环只进行1次。分别对应的是最坏的情况和最好的情况,而基本操作比较操作,分别为 1 2 n 2 − 1 2 n \frac{1}{2}{n^2}-\frac{1}{2}{n} 21n221n次和n-1次。这时,算法的效率不仅与问题规模n有关,还与输入数据的取值有关。而时间复杂度通常取最坏的情况 O O O(n2)。

说明:在有的时候,也可以考虑平均的时间复杂度,所谓平均的时间复杂度是在统计概率的情况下。比如,初始的序列是随机的,也就是出现任何情况的概率都是相同的,这时可以取最好情况下和最坏情况下的平均作为它的平均时间复杂度。对于冒泡排序来说,它的平均时间复杂度仍为 O O O(n2)。

五、算法的存储空间需求
与算法的时间复杂度类似,对应讨论的是算法的(渐进)空间复杂度。
算法的空间复杂度: S ( n ) = O ( g ( n ) ) S(n)=O(g(n)) S(n)=O(g(n))表示随着问题规模n的增大,算法运行所需存储量的增长率与g(n)的增长率相同。

算法的存储量包括:
1、输入数据所占的空间
2、程序本身所占的空间
3、辅助变量所占的空间

说明:任何算法写成程序后,本身都会占有一定的空间,不同的算法占有的空间可能会不同,但是这个差距是细微的,一般情况下,可以不考虑。若输入数据所占空间只取决于问题本身,则只需要分析除输入和程序之外的辅助变量所占的额外空间
若所需的额外空间相对于输入数据量来说是一个常数,则称此算法为原地工作
若所需的额外空间依赖于特定的输入,则通常按最坏的情况考虑。

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在计算机科学中,算法时间复杂度空间复杂度衡量算法效率的两个重要指标。 时间复杂度指的是算法执行所需的时间量,通常用大 O 记法表示。例如,如果一个算法时间复杂度为 O(n),那么它的执行时间随着输入数据规模 n 的增加而线性增长。常见的时间复杂度包括常数时间 O(1)、线性时间 O(n)、对数时间 O(log n)、平方时间 O(n^2)、立方时间 O(n^3)等等。通常,我们希望算法时间复杂度越小越好,因为这意味着它可以更快地处理大规模数据。 空间复杂度指的是算法在执行过程中所需的内存空间,也通常用大 O 记法表示。例如,如果一个算法空间复杂度为 O(n),那么它所使用的内存空间随着输入数据规模 n 的增加而线性增长。常见的空间复杂度包括常数空间 O(1)、线性空间 O(n)、对数空间 O(log n)、平方空间 O(n^2)、立方空间 O(n^3)等等。通常,我们也希望算法空间复杂度越小越好,因为这意味着它可以在更小的内存空间中运行。 需要注意的是,算法时间复杂度空间复杂度通常是相互矛盾的。例如,为了降低时间复杂度,可能需要增加空间复杂度,反之亦然。因此,在实际编写算法时,需要根据具体情况综合考虑时间复杂度空间复杂度。 ### 回答2: 时间复杂度空间复杂度是评估算法效率的两个重要指标。 时间复杂度是指算法执行所需要的时间和问题规模之间的关系。在分析时间复杂度时,通常计算算法中的基本操作执行次数。时间复杂度用大O表示法表示,例如O(1)表示常数时间复杂度,O(n)表示线性时间复杂度,O(n^2)表示平方时间复杂度等。时间复杂度越低,算法执行所需时间越短。 空间复杂度是指算法执行所需要的额外空间和问题规模之间的关系。在分析空间复杂度时,通常计算算法所需的额外空间大小,包括变量、数组、堆栈、队列等。空间复杂度同样使用大O表示法表示,例如O(1)表示常数空间复杂度,O(n)表示线性空间复杂度,O(n^2)表示平方空间复杂度等。空间复杂度越低,算法所需的额外空间越少。 时间复杂度空间复杂度是相互影响的。通常情况下,时间复杂度较低的算法往往需要更多的额外空间,而空间复杂度较低的算法往往需要更多的时间。因此,在算法设计时,需要综合考虑时间复杂度空间复杂度,选择更合适的算法。 总而言之,时间复杂度空间复杂度是对算法效率的度量,用于评估算法执行所需的时间和额外空间。通过分析算法时间复杂度空间复杂度,可以选择更优的算法,提高程序的执行效率。 ### 回答3: 在计算机科学中,算法时间复杂度空间复杂度衡量算法优劣的重要指标。 时间复杂度是用来衡量算法执行所需时间的度量。它表示随着输入规模的增长,算法所需要执行的基本操作的数量。常见的时间复杂度有常数时间O(1)、线性时间O(n)、对数时间O(log n)、平方时间O(n^2)等。时间复杂度越小,算法的执行速度越快。 空间复杂度是用来衡量算法执行所需空间的度量。它表示随着输入规模的增长,算法所需要的额外空间的数量。常见的空间复杂度有常数空间O(1)、线性空间O(n)、对数空间O(log n)、平方空间O(n^2)等。空间复杂度越小,算法所需的内存空间越少。 在分析时间空间复杂度时,一般采用最坏情况下的复杂度作为评估标准,因为最坏情况下的复杂度能够保证算法的性能。同时,复杂度只是一种理论上的度量,实际运行结果可能受到硬件环境、编译器优化等因素的影响。 衡量和比较算法时间复杂度空间复杂度对于优化算法和选择合适的算法非常重要。在实际开发中,我们需要根据具体的应用场景和需求,选择适合的算法来平衡时间和空间的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值