这里有业余爱好者,我正在阅读CLS,我在分析内容方面遇到了麻烦。主要是因为我不太擅长从不同类型的循环和东西中找出总结。无论如何,我写了一个解释和一些示例代码来向您展示我的意思。我认为这是对的,但我收到来自不同来源的混合信息。首先,这里是C ++中的一些示例代码,您会注意到它包含对整数n的引用以及它的几个递增。那些被放在那里计算每个陈述用多少次作为检查它的方式。
int *intSelSort(int a[], int size, int &n){
int i, k, in;
for(int j = 0; ++n && j < size -1; j++){
k = a[j];
n++;
for(int i = j+1; ++n && i < size; i++)
if(++n && a[i] < k){
k = a[i];
in = i;
}
a[in] = a[j];
a[j] = k;
n+=2;
}
return a;
}
这个例子,当与一个长度为5的数组一起使用时,n的值为41.除了最里面的for循环条件中的计数之外,所有计数都被删除了。计数为14.这对以后很重要。
无论如何,CLS做的事情有点不同,首先是它使用从1开始的伪代码和数组索引。我写了一些来反映他们的工作
//[1][2][3][4][5]
//Highest j is 4, i is 5
int k, index; //O(1)
n = A.Size //O(1)
for j = 1, j < n, j++ do //O(N)
k = A[j] //O(N - 1)
for i = j + 1, i <= n, i++ do //O((n^2 + n - 2)/2)
if(A[i] < k) //O((n^2 - n)/2)
k = A[i] //O(c)
index = i //O(c)
A[index] = A[j] //O(N - 1)
A[j] = k //O(N - 1)
(如果n = 5,首先进行5次比较,计算额外费用) (然后是4,3,2,1)
2,3,4,5,6(n - 0)比较
3,4,5,6(n - 1)比较
4,5,6(n - 2)次比较
5,6(n - 3)次比较
[j = 5,i = 6],退出循环,无比较
(n - 0)+(n - 1)+(n - 2)+(n - 3)= 4n - 6个比较,14。
或更一般地,
sum(n-N)_(0-> N = n-2)=
sum(n)(0 - > N = n - 2) - sum(N)(0 - > N = n - 2)=
n(n - 2 + 1) - ((n - 1)(n - 2))/ 2 =(n ^ 2 + n - 2)/ 2
如果n = 5,则得到14.确切地说是测试中的步骤数。
对于for循环中的if ,
sum(n-N-1)_(0-> N = n-2)
=(n ^ 2 + n - 2)/ 2 - sum(1)_(0 - > N = n - 2)
=(n ^ 2 + n - 2)/ 2 - (n - 1)=(n ^ 2 - n)/ 2,或者在这种情况下,10比较
单独测试最内层的if语句也产生了10个比较。
C取决于if语句是否为真。 案例一:列表已经排序,if语句永远不会 是的,因此永远不会调用那里的语句。
案例二:列表反向排序,调用if语句 楼层(N / 2)次?
5 4 3 2 1
1 4 3 2 5
1 2 3 4 5
9 8 7 6 5 4 3 2 1
1 8 7 6 5 4 3 2 9
1 2 7 6 5 4 3 8 9
1 2 3 6 5 4 7 8 9
1 2 3 4 5 6 7 8 9
还有其他情况,if语句更多次是真的吗? 有没有办法证明if语句的子语句是 时间复杂度n或更少,所以我可以忽略它们?他们是O(n)? 我在这里犯了很多错误吗?我见过不同的网站 这个总和公式,所以我不确定。
答案 0 :(得分:0)
我认为你的分析是正确的。
最后的问题:
对于序列n, 1, 2, ..., n-1
,if语句是n-1次为真(并且两个元素的n-1次被交换。)
对于相反的顺序,它不是下限(N / 2)。它是
N-1 + N-3 + N-5 + ... + 0 =Σ i = 0,...⌊N/2⌋ N-1-2⋅i≈(( N-1)·N)/ 2
和⌊N/2⌋次两个元素被交换。
但由于if语句主体中操作的O(1)复杂性,因此if语句的真实性并不重要。您的分析非常精确。如果您使用big-O表示法,则没有必要这样做。让我简化你的例子:
int k, index; // O(1)
n = A.Size // O(1)
for j = 1, j < n, j++ do // O(N) - runs n-1 times
k = A[j] // O(1) - takes only 1 step but is executet O(N) times.
for i = j + 1, i <= n, i++ do // O(N) - the first run takes n-1 steps -+
if(A[i] < k) // O(1) - this can be evaluated in 1 step |- together 1 to 3 steps. So the whole if block is in O(1).
k = A[i] // O(1) - this is at worst 1 more step -+
index = i // O(1) - this also
A[index] = A[j] // O(1) - one step executet O(N) times
A[j] = k // O(1) - one step executet O(N) times
注意:这不是整体的复杂性,而只是代码中每个代码项的复杂性。
现在你只需要增加嵌套的复杂性,就可以得到
的整体复杂性O(N)·O(N)·O(1)= O(N 2 )。
如果您对更精确的分析感兴趣,可以将嵌套for循环的复杂性降低到O(N-i),并将i的总和从1加到N-1。
O(N-1)+ O(N-2)+ ... + O(N-N + 1)= O((N-1)·N / 2)= O(N 2功能)
另请注意,大O符号和算法的复杂性无法直接转换为算法的执行时间或步骤数。