我目前正在了解各种基本算法(排序,搜索等),我发现大多数书都在谈论计算所述算法的效率(O(n logn)等)。
在计算这些时,一些作者通常称比较为基本操作(最昂贵),然后计算出整个算法中出现了多少这些算法,然后最终给出它的渐近符号。
例如,对于强力选择排序,这是我在Wikipedia上看到的算法:
int i,j;
int iMin;
for (j = 0; j < n-1; j++) {
iMin = j;
for ( i = j+1; i < n; i++) {
if (a[i] < a[iMin])
iMin = i;
}
if(iMin != j)
swap(a[j], a[iMin]);
}
这就是对效率分析的说法:
与其他排序算法相比,选择排序并不难分析,因为没有一个循环依赖于数组中的数据。选择最低元素需要扫描所有n个元素(这需要进行n-1次比较),然后将其交换到第一个位置。找到下一个最低元素需要扫描剩余的n - 1个元素,依此类推,对于(n - 1)+(n - 2)+ ... + 2 + 1 = n(n - 1)/2∈Θ(n ^ 2)比较(参见算术级数)。这些扫描中的每一个都需要一次交换n-1个元素(最终元素已经到位)。
如果我错了,请纠正我,但在我看来,比较a[i] < a[iMin]
被认为是这里最昂贵的操作。
为什么不在for循环头和交换操作中进行比较和增量?
P.S。:我知道这个网站上有几百个关于每个渐近符号意味着/代表什么的问题,但这不是我所要求的。我也知道有更有效的算法可以排序,但这也不是我所要求的。
答案 0 :(得分:2)
实现算法的循环和其他代码基础结构与比较次数成比例。粗略地说,对于循环的每次迭代,将进行比较。交换操作将以比较的其他比例发生,并且每个项目需要一些其他数量的工作。实际上,这意味着每次比较的机器指令的实际计数大于比较本身的工作量。但是,这不是big-O表示法的重要部分。
目的是描述两种不同输入尺寸之间的增长率。每项项目的工作是每次比较两条指令还是四条指令无关紧要。如果算法是O(n ^ 2)并且您的输入n是100,那么差值20000到40000.如果输入是1000,则它是2000000到4000000.将其与O(n * Log(n))进行比较,这将是是(2 * 3 * 1000)与(4 * 3 * 1000)。显然,重要的部分是零的数量,而不是前导数字。
换句话说,通过购买速度提高一倍的计算机,您可以解决2对4的问题。您无法通过这种方式解决算法之间的差异。实现算法总会有一些计算工作系数。别担心;担心必须多久执行一次这项工作。