分析以下排序算法:
for (int i = 0; i < SIZE; i++)
{
if (list[i] > list[i + 1])
{
swap list[i] with list[i + 1];
i = 0;
}
}
我想确定时间复杂度,在更糟糕的情况下...我不明白它是如何O(n ^ 3)
答案 0 :(得分:1)
好的..这里...... 在最坏的情况下,我们可以说我们有一个完全翻转的阵列..
9 8 7 6 5 4 3 2 1 0
每次交换时,我都会重置为0.
让我们开始翻转9 8:我们现在有8 9 7 6 5 4 3 2 1 0并且i被设置回零。
现在循环运行到2并且我们再次翻转..:8 7 9 6 5 4 3 2 1 0我再次重置..但是为了得到7到第一个位置我们有另一个翻转为8和7。 :7 8 9 6 5 4 3 2 1 0
所以循环次数如下:
T(1)= O(1) T(2)= O(1 + 2) T(3)= O(1 + 2 + 3) T(4)= O(1 + 2 + 3 + 4)等等..
最后对于第n个项,在这种情况下最大的是T(n)= O(n(n-1)/ 2)。
但是对于整个事情,你需要总结所有这些条款 其中可以用(T(n))=((n ^ 2)的求和)=(n ^ 3)
的总和来定义<强>加成强> 可以这样想:对于每个元素,你需要去它并把它带回来..但当你把它带回来时它只是一个空间。我希望这更清楚一点。
另一个编辑 如果上述任何一点没有意义。可以这样想:你必须将0带到数组的前面。你最初走到零9步并把它放在1之前。但之后你被神奇地运送(i = 0)到数组的开头。所以现在你必须走8步到零,然后把它放在两个位置。扎普!你回到了数组的开始。你必须采取多少步骤才能使每次达到零,以便它在正面。 9 + 8 + 7 + 6 + 5 + ..这是重复的最后一个项,因此受阵列长度的平方限制。这有意义吗?现在为平均每个元素执行此操作,你正在做O(n)工作..对吗?这意味着将所有条款相加起来..而且我们有O(n ^ 3)。
如果事情有帮助或没有意义,请评论。
答案 1 :(得分:1)
显然,for
循环本身就是O(n)。问题是,它可以运行多少次?
每次进行交换时,循环都会重新开始。你会做多少次交换?您将从每个元素的起始位置开始交换,直到它到达排序输出中的正确位置。对于反向排序的输入,将平均为n / 2次,或再次为O(n)。但这是每个元素,给另一个O(n)。这就是你如何到达O(n ^ 3)。
答案 2 :(得分:1)
我对n = 10和n = 100进行了分析。比较的数量似乎是O(n 3 )这是有道理的,因为我将n设置为0的平均值所以它在你的for循环的n 2 *(n / 2)比较和递增操作的某处,但是交换的数量似乎只有O(n 2 )因为显然不再需要交换来整理整个列表。最好的情况仍然是n-1比较和0交换。
对于最佳情况测试,我使用已排序的n个元素数组:[0 ... n-1]。
对于最坏情况测试,我使用n个元素的反向排序数组:[n-1 ... 0]
def analyzeSlowSort(A):
comparison_count = swap_count = i = 0
while i < len(A) - 1:
comparison_count += 1
if A[i] > A[i+1]:
A[i], A[i+1] = A[i+1], A[i]
swap_count += 1
i = 0
i += 1
return comparison_count, swap_count
n = 10
# Best case
print analyzeSlowSort(range(n)) # ->(9, 0)
# Worst case
print analyzeSlowSort(range(n, 0, -1)) # ->(129, 37)
n = 100
# Best case
print analyzeSlowSort(range(n)) # ->(99, 0)
# Worst case
print analyzeSlowSort(range(n, 0, -1)) # ->(161799, 4852)
显然,就比较而言,这是一种非常低效的排序算法。 :)