我对选择的分析是否正确?

时间:2014-01-16 03:07:00

标签: sorting big-o complexity-theory time-complexity

这里有业余爱好者,我正在阅读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)? 我在这里犯了很多错误吗?我见过不同的网站 这个总和公式,所以我不确定。

1 个答案:

答案 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符号和算法的复杂性无法直接转换为算法的执行时间或步骤数。