请注意,我在此处使用插入排序作为示例。我在C.S.课程中获得了一项任务,其中包括将各种排序算法的运行时间与应该发生的理论运行时间进行比较。
例如,假设我有一个1000个随机排序整数的输入数组,并且我在最坏情况假设的情况下运行。结果可能在320.x milliseconds
附近。然而,从理论上讲,它应该是平坦的300 milliseconds
。同样,如果我将输入大小提高到6000,我可以获得11,735.577106 milliseconds
(如我的C.S.老师提供的示例所示);然而,理论运行时间为10,800 milliseconds
。
我们知道插入排序的最坏情况是f(n) = O(n^2)
。不知道f
的原始定义,我查了一下,发现结果是,
f(n) = ( n(n - 1) + n ) / 2 = n^2 / 2
。
这引出了我对算法的递归关系:
T(n) = T(n-1) + f(n)
所以,我决定写一个小C程序并测试T(n)
输入为1000,期望大约300000左右。
#include <stdio.h>
// Recurrence relation for insertion sort ( worst-case )
float T( float n )
{
if ( n == 1.0f )
return 1.0f;
return T( n - 1 ) + n * n * 0.5f;
}
int main( void )
{
printf( "T( %f ) = %f \n", 1000.0f, T( 1000.0f ) );
return 0;
}
输出:
T( 1000.000000 ) = 166916608.000000
显然,情况并非如此。
所以,我很难过。
TL;博士
我想知道我的教授在理论运行时间达到300毫秒,使用1000个元素的插入排序。我的理解是使用递归关系来解决这个问题,但所显示的代码的输出(应该是插入类型的最坏情况的递归关系)并不能提供任何明确的方法。了解这实际是如何计算的。
答案 0 :(得分:0)
如果要测试最坏的情况,请创建一个按降序排序的数组,并使用插入排序进行升序排序。
您最好的情况是,如果您采用升序排序数组并尝试通过插入排序运行它。
获取两者的基准并尝试将它们关联起来。
O(n ^ 2)也不完全等于n ^ 2个运算。在Big-O表示法中,O(2(n ^ 2))和O((n ^ 2)/ 2)都将表示为O(n ^ 2)
答案 1 :(得分:0)
你的复发是不对的;在最坏的情况下计算比较,它应该是T(0)= 0; T(n)= T(n - 1)+ n - 1,因为在最坏的情况下,它需要进行n - 1次比较才能插入长度为n - 1的有序数组中。解是T(n)= n(n - 1)/ 2。你的复发具有立方复杂性,这就是程序输出结束的原因。
答案 2 :(得分:0)
首先要定义插入排序的工作原理,它将向我们展示它如何随着时间的推移而增长。
插入排序是一种算法,它采用n个数字的列表,并将它们逐个插入到新的列表中(最初为空),确保每个数字都插入其位置,最后有序列表。
首先要注意的是,我们会从列表中读取每个数字一次,这意味着我们首先n
。
然后,对于我们阅读的每个号码,我们首先插入到列表的末尾,以便进行1
操作。
然后我们必须将它与新列表中的先前值进行比较,如果它小于之前的值,我们交换并重复直到条件无效,以便{{1每个比较&amp;的操作交换,但有多少比较&amp;交换我们有问题。
我们会将所有非变体操作视为常量1+3
。
我们考虑最坏的情况,在最坏的情况下,每个数字都证明它必须转移到列表的开头。
对于C
次读取,最糟糕的情况是它必须移i
次,其中i-1
。
总的来说,我们有:
1 <= i <= n
然后我们将时间复杂度变为渐近的Big-O:
Time = T(shift(1)) + T(shift(2)) + .. + T(shift(n))
Time = C * (0 + 1 + 2 + .. + (n-1))
Time = C * (1/2 (n-1)n)
Time = C * (1/2 n^2 - 1/2 n)