我正在尝试理解算法的概念,以及它们如何提高计算机程序的性能。
所以假设,我必须编写一个程序来生成一个数字列表,
从数字1开始。
为其添加3。
将结果(1 + 3 = 4)存储在列表中。
为新号码添加5。
将结果(4 + 5 = 9)存储在列表中。
另外,将3和5添加到列表中的最新号码。
现在这是一个非常简单的程序,让我们说程序必须在数字大于10,00,000时停止,并且假设一个简单的程序执行此操作需要10秒来生成列表。
如何为此问题设计算法,以便程序花费更少的时间来生成列表。
注意 - 我试图通过一个例子来理解这里的概念,上面提到的时间是随机的而不是事实的。如果有人可以帮助我用一个“简单”的例子来理解这个概念,如果他们不想使用上面的例子那就太棒了。
答案 0 :(得分:7)
您上面给出的内容(生成列表的步骤列表)是算法。
效率的显着提高通常意味着从一种算法转换到另一种算法,以较少的工作完成相同的目标。例如,对于上面的算法,您可能会尝试完全避免创建列表(如此),而是替换可以快速生成列表中任何特定点的结果的算法 - 给定N作为输入,它将做点什么
int n = N/2;
int m = N-n;
return 1 + n * 3 + m * 5;
请注意,这段代码可能并不完全正确(我认为它不能正确处理奇数与偶数输入数字),但是您可以得到一般的想法 - 而不是执行一系列操作来获得一个结果,它执行的操作数量要少得多,以产生相同的结果。
答案 1 :(得分:1)
在你给你的例子中,你的速度要快得多。您必须输出整个列表,您所描述的算法才能有效地完成。
让我们稍微修改一下这个问题:你只输出第一个数字大于1000000的数字。这可以比生成整个列表更聪明地解决。
答案 2 :(得分:1)
当人们着眼于改进程序或代码片段的性能时(即使用更好的算法来计算相同的结果),重要的是要考虑算法的可见输出。也就是说如何使用或消耗(算法的输出)算法?换句话说,该算法返回什么,以及该消耗是如何消耗的?
你问题中的上述步骤表明应该建立一个列表,但那么什么?如果仅仅丢弃结果(您可以轻松编写这样的程序或函数),优秀的优化器(人或机器)可以基于从未使用结果的事实替换空或空程序或函数。 (说真的:这是基准测试中的一个常见问题,算法计算一些结果来测量生成代码的性能,但结果没有使用,因此编译器删除了可能的整个循环,内存分配,可能是整个函数!)
因此,关于如何更改算法以获得更好性能的分析问题的设置真正重要的是:识别或指定使用的输出部分(由程序的其他部分组成) )。
给定一个规范(算法的结果如何被消耗),我们可以向后工作以找到算法改进,以减少工作量产生相同的结果。
当我们编写算法时,我们可以通过合成来识别改进的机会。换句话说,上面描述的算法可能被其他算法用于一次只找到一个值,这意味着Jeffry的解决方案是适当的更好的替换算法。
但是,列表算法的不同消费者可能会请求其可见效果的不同部分,因此不同的优化或算法替换可能是合适的。如上所述,如果结果根本没有使用,情况就是如此,但是,另一个消费者可能只想计算列表中的节点数,在这种情况下,完全不同的优化更合适。
在某些情况下,我们可以指定算法返回一些内容,并且我们不得不出于某种原因生成代码而不知道谁在使用结果。在这些情况下,优化器(人或机器)将被迫做出一种悲观的假设,即返回的每个可见效果都可能被消耗掉。例如,让我们假设列表是返回的(作为问题中的附加规范),并且我们阻止任何优化器进一步看到消耗,我们很可能必须实际构建列表(等等)杰弗里的回答是行不通的。)
简而言之,我们无法在没有额外背景的情况下完全分析问题及其解决方案空间。
在某种程度上,附加上下文采用显式返回语句的形式(或其他一些外部可见的副作用,例如修改全局变量)。
此外,一些额外的上下文可能采用另一种算法的形式,即封闭,调用或组合(使用感兴趣的原始算法);因此,优化过程是递归的,并且(人或机器)可以“看到”的次数越多,结果越好。
答案 3 :(得分:0)
让我们开始说你没有使用算法来提高计算机程序的性能;算法 程序(根据定义,算法是解决问题的有限操作序列)。
当然有着名的算法,已经由聪明人发明,可以完美地应用于问题(你的问题是关于图?Dijkstra的最短路径算法,Ford-Fulkerson最大流量,Prim和Kruskal算法最小生成树,等等)。您通常希望在程序中重复使用这些性能良好的算法,而不是从头开始重写它们。
你会想要使用它们,因为
对于数字1,也涉及一些数学计算,因为要测量算法的性能,你必须做一些更好解释的事情here
希望我明白解决你的疑惑,不幸的是我不喜欢大字符和这样的性能计算所以我不能仅仅指向维基百科链接更有帮助