什么是比较算法的好度量



我读了一篇文章,是关于比较两种算法的。

我的老师告诉我,你可以直接用算法的步数来分析算法。

为例:

algo printArray(arr[n]){
    for(int i=0;i<n;i++){
    write arr[i];
    }
}

的复杂度为O(N),其中N为数组的大小。并对N重复for循环数次。

,

algo printMatrix(arr,m,n){
    for(i=0;i<m;i++){
        for(j=0;j<n;j++){
        write arr[i][j];
        }
    }
}
M=N时,

具有O(MXN) ~ O(N^2)的复杂度。for中的语句执行MXN次。

类似O(log N)。如果它把输入分成两等份。等等。

但是根据那篇文章:

度量Execution Time, Number of statements不适合分析算法。

因为:

Execution Time 将是系统依赖的,

Number of statements 将根据所使用的编程语言而变化。

和它声明

理想解将算法的运行时间表示为输入大小N的函数,即f(n)

这让我有点困惑,如果你认为执行时间不是一个好的衡量标准,你怎么能计算运行时间呢?

请各位专家详细说明一下好吗?

提前感谢。

当你说"O(N)的复杂性"时,它被称为"大O符号",这与你在你的帖子中提到的"理想解决方案"相同。它是将运行时间表示为输入大小的函数的一种方式。

我认为你感到困惑的是当它说"表示运行时间"-它不是指用数值表示它(这是执行时间),它意味着用大o符号表示它。我想你只是在术语上犯了错误。

执行时间确实与系统有关,但它也取决于算法执行的指令数量。

而且,我不明白为什么步数是无关的,因为算法被分析为语言不可知的,而不关注各种语言的特征和语法糖。

自从我开始分析算法以来,我总是遇到的算法分析的一个度量是执行指令的数量,我没有看到这个度量可能是不相关的。

同时,复杂度类的意思是作为一个"数量级"来表示算法的快慢。它们依赖于执行指令的数量,并且独立于算法运行的系统,因为根据定义,一个基本操作(例如两个数字的加法)应该花费常数时间,无论这个"常数"在实践中是大是小,因此复杂度类不会改变。复杂度函数表达式中的常量确实可能因系统而异,但与算法比较实际相关的是复杂度类,因为只有通过比较这些才能发现与另一种算法相比,当输入(渐近)越来越大时,算法的行为

大0符号可以消除常数(固定成本和常数乘数)。因此,任何需要kn+c操作来完成的函数都是(根据定义!)O(n),不管kc。这就是为什么用实际数据对你的算法进行实际测量(分析)通常更好,以查看它们的有效速度有多快。

但是执行时间显然取决于数据集——如果你试图根据特定的使用场景提出一个通用的性能度量而不是,那么执行时间就不那么有价值了(除非你在相同的条件下比较所有算法,即使这样,它也不一定公平,除非你对大多数可能的场景建模,而不仅仅是一个)。

当你移动到更大的数据集时,

Big-O符号变得更有价值。它让您大致了解算法的性能,假设kc 的值是合理的。如果您有一百万个数字要排序,那么可以肯定地说,您希望远离任何O(n^2)算法,并尝试找到更好的O(n lg n)算法。如果你对三个数字进行排序,理论上的复杂度界限就不再重要了,因为常量决定了所占用的资源。

还要注意,虽然给定算法的语句数可以在编程语言之间有很大差异,但需要执行的恒定时间步骤的数量(在您的目标体系结构的机器级别上,通常是整数运算和内存访问需要固定时间,或者更准确地说,是由固定时间限制的)。这就是big-O度量的算法所需的最大固定成本步骤数的界限,它与给定输入的实际运行时间没有直接关系,但仍然大致描述了给定数据集随着规模的增长必须完成的工作的数量。

在比较算法时,执行速度很重要,其他人也提到过,但其他因素,如内存空间也很重要。

内存空间也使用复杂度顺序表示法。

代码可以使用冒泡排序对数组进行就地排序,只需要少量额外的内存0(1)。其他方法虽然更快,但可能需要O(ln N)内存。

其他更深奥的指标包括代码复杂度,如圈复杂度和可读性

传统上,计算机科学通过比较次数或有时使用"大O符号"来衡量算法的有效性(速度)。之所以如此,是因为比较(和/或数据访问)的数量是描述某些算法效率的一个很好的数学模型,特别是搜索和排序算法,其中O(log n)被认为是理论上最快的。

这个理论模型一直有一些缺陷。它假设比较(和/或数据访问)是需要时间的,而执行函数调用和分支/循环之类的事情的时间可以忽略不计。这在现实世界中当然是无稽之谈。

在现实世界中,递归二进制搜索算法可能会非常慢,例如与快速&使用普通的for循环实现脏线性搜索,因为在给定的系统上,函数调用开销是花费最多时间的,而不是比较。

影响性能的因素有很多。随着cpu的发展,更多这样的东西被发明出来。现在,您可能需要考虑数据对齐、指令管道内衬、分支预测、数据缓存、多CPU内核等问题。这些技术使得传统的算法理论变得无关紧要。

为了写出最有效的代码,你需要在脑海中有一个特定的系统,并且你需要对该系统有深入的了解。幸运的是,编译器也发展了很多,所以很多深入的系统知识可以留给为特定系统实现编译器端口的人。

总的来说,我认为现在很多程序员花了太多时间考虑程序速度,想出"聪明的东西"来获得更好的性能。在cpu很慢、编译器很糟糕的时候,这些东西非常重要。但是今天,优秀的现代程序员关注的是使代码无bug、可读、可维护、可重用、安全、可移植等。不管你的程序有多快,如果它是一堆乱七八糟的不可读的垃圾。因此,在需要时处理性能问题。

最新更新