我目前已经学会了所有使用的排序算法的代码,并了解它们的功能。然而,作为其中的一部分,人们还应该能够找到时间和空间的复杂性。我看到人们只是看着循环并得出复杂性。有人可以指导我实现这一目标的最佳实践。给定的示例代码用于" Shell sort"。从代码本身理解和计算的策略应该是什么。请帮忙!像步数法这样的东西。需要了解我们如何从代码本身进行渐近分析。请帮忙。
int i,n=a.length,diff=n/2,interchange,temp;
while(diff>0) {
interchange=0;
for(i=0;i<n-diff;i++) {
if(a[i]>a[i+diff]) {
temp=a[i];
a[i]=a[i+diff];
a[i+diff]=temp;
interchange=1;
}
}
if(interchange==0) {
diff=diff/2;
}
}
答案 0 :(得分:3)
由于绝对下限在比较 - 排序算法的最坏情况下 O(n log n),显然可以&做得更好。同样的复杂性在这里。
最差时间复杂度:
<强> 1。内循环
让我们首先开始分析内循环:
for(i=0;i<n-diff;i++) {
if(a[i]>a[i+diff]) {
temp=a[i];
a[i]=a[i+diff];
a[i+diff]=temp;
interchange=1;
}
}
由于我们对此级别a
的结构知之甚少(任何事情),因此条件肯定可能存在,因此发生交换。因此,保守分析表明,interchange
可能在循环结束时为0
或1
。然而,我们知道如果我们将第二次执行循环,具有相同的diff
值。
当您评论自己时,循环将执行 O(n-diff)次。由于循环内的所有指令都需要恒定的时间。循环本身的时间复杂度也是 O(n-diff)。
现在的问题是,在interchange
转向1
之前,0
可以O(n^2/diff-n)=O(n^2/diff-n)
多少次。最大限度是放置在绝对右边的项目是最小元素,因此将保持&#34;交换&#34;直到它到达列表的开头。因此内循环本身最多重复:O(n / diff)次。因此,循环的计算工作是最坏的情况:
diff
<强> 2。具有不同diff
外部循环依赖于n/2
的值。从值interchange
开始,在循环结束时给定1
等于diff
,我们无法证明的情况不是这样,将使用{{1执行新的迭代被设置为diff/2
。重复此过程直至diff < 1
。这意味着diff
将2
的所有权力提升至n/2
:
1 2 4 8 ... n/2
现在我们可以通过总结进行分析:
log2 n
------
\
/ O(n^2/2^i-n) = O(n^2)
------
i = 0
其中i
表示给定迭代的* log 2 (diff)。如果我们解决这个问题,我们会得到 O(n 2 ) 最差时间复杂度。
注意(在最坏情况比较排序的下限):可以证明没有比较排序算法,最坏情况时间复杂度 O(n log n)< / em>的
这是因为对于包含 n 项目的列表,有 n!可能的排序。对于每个排序,需要重新组织列表的方式不同。
由于使用比较可以将可能的排序集合分成两个等于最佳的部分,因此至少需要 log 2 (n!)比较才能找到我们正在讨论哪种排序。 log 2 (n)的复杂性可以使用 Stirling近似计算:
n /\ | | log(x) dx = n log n - n = O(n log n) \/ 1
最佳情况时间复杂度:在最好的情况下,列表显然是有序的。在这种情况下,内部循环将永远不会执行if-then
部分。因此,interchange
将不会设置为1
,因此在执行for
循环后一次。外部循环仍将重复 O(log n)次,因此时间复杂度为 O(n log n) 。
答案 1 :(得分:0)
查看循环并尝试确定它们执行的次数。从最里面的那些开始。
在给定的示例中(不是最容易开始的),for {loop(最里面)在i
范围内[0,n-diff]
被执行,即它被执行n-diff
次
在该循环中所做的事情并不重要,只要它需要&#34;常数时间&#34;,即存在有限数量的原子操作。
现在只要diff>0
执行外循环。这种行为很复杂,因为迭代可以减少diff
或不减少(当没有找到反对时它会减少)。
现在你可以说diff
将减少log(n)
次(因为它减半,直到0),并且在每次减少之间内部循环运行&#34;一定次数&# 34。
运动的眼睛也会识别出与泡泡相关的交错传递,并得出结论,这个次数不会超过所涉及的元素数量,即n-diff
,但这可以说是所有可以说的&# 34;一目了然&#34;。
算法的完整分析是一个可怕的混乱,因为数组逐渐变得更好,更好地排序,这将影响内循环的数量。