【问题标题】:How to count number of comparisons and number of moves(swaps) in Merge Sort [C++]如何在合并排序 [C++] 中计算比较次数和移动(交换)次数
【发布时间】:2020-05-11 17:52:51
【问题描述】:

我正在尝试计算合并排序中的交换和比较次数。

#include<iostream>

using namespace std;

int comparisons = 0;
int moves = 0;

void merge(int arr[], int l, int m, int r)
{
    int i, j, k;
    int n1 = m - l + 1;
    int n2 = r - m;

    int* L = new int[n1];
    int* R = new int[n2];

    for (i = 0; i < n1; i++)
        L[i] = arr[l + i];
    for (j = 0; j < n2; j++)
        R[j] = arr[m + 1 + j];

    i = 0;
    j = 0;
    k = l;
    while (i < n1 && j < n2)
    {
        if (L[i] <= R[j])
        {
            arr[k] = L[i];
            moves++;
            i++;
        }
        else
        {
            arr[k] = R[j];
            moves++;
            j++;
        }
        k++;
        comparisons++;
    }

    while (i < n1)
    {
        arr[k] = L[i];
        moves++;
        i++;
        k++;
    }

    while (j < n2)
    {
        arr[k] = R[j];
        moves++;
        j++;
        k++;
    }
}

void mergeSort(int arr[], int l, int r)
{
    if (l < r)
    {
        int m = l + (r - l) / 2;

        mergeSort(arr, l, m);
        mergeSort(arr, m + 1, r);

        merge(arr, l, m, r);
    }
}

int main()
{
    int size;
    cout << "Enter size: " << endl;
    cin >> size;

    int* arr = new int[size];

    for (int i = 0; i < size; i++) {
        arr[i] = rand() % 100;
    }

    for (int i = 0; i < size; i++) {
        cout << arr[i] << " ";
    }

    cout << endl << endl;

    mergeSort(arr, 0, size - 1);

    for (int i = 0; i < size; i++) {
        cout << arr[i] << " ";
    }

    delete[] arr;

    cout << endl;

    cout << "The number of comparisons: " << comparisons << endl;
    cout << "The number of moves: " << moves << endl;

    cout << endl;

    system("pause");
    return 0;
}

如果我做一个10个元素的数组,比较次数应该是10 * log2(10) = 33(公式:比较次数= n* log2n)。而我的程序输出24,所以不正确。 移动次数应该是 2 * 10 * log2(10) = 66 (公式:移动次数= n* log2n)。我的程序输出 34,所以它也不正确。 请解释我如何正确地做到这一点。我哪里做错了?

【问题讨论】:

  • 你有没有试过用调试器运行程序,看看在哪里计算这些不存在的比较或移动?
  • 您的预期计数依据是什么?
  • 无关:我看到int* arr = new int[size];int* L = new int[n1];int* R = new int[n2];,但我只看到delete[] arr;
  • 您将复杂性与实际比较混淆了。 O(n log n) 是平均/最坏情况复杂度。例如当输入已经排序时,那么交换的次数就会少很多
  • 是的,我试过用调试器运行程序,但是我这方面做得很差,所以在调试的时候没有发现任何错误。

标签: c++ sorting mergesort


【解决方案1】:

如前所述,您将复杂性与具体指令的执行次数混淆了。我们来看看这段代码sn-p。
`

#include <iostream>
 #include <vector>
 using namespace std; //don't do this at home
 void exempleFunction(vector<int>& v){ //size of v is n
     for(int i = 0; i < v.size(); i++){
         if (i==0){
             swap(v[0], v[1]);
         }
     }
 }
 int main(){
     int n;
     std::cin>>n;    //n > 1
     vector<int> v(n);
     readVector(n); //gets the values of the vector
     exempleFunction(v);
 }`

在此代码中,exempleFunction() 的开销为 O(n),无论 n 的值如何,swap 执行的次数都是 1。 说了这么多,让我们看一下这段代码:

``#include <iostream>
  #include <vector>
  using namespace std; //don't do this at home
  void exempleFunction(vector<int>& v){ //size of v is n
      for(int i = 1; i < v.size(); i++){
          swap(v[i], v[i-1]);
      }
  }
  int main(){
      int n;
      std::cin>>n;    //n > 1
      vector<int> v(n);
      readVector(n); //gets the values of the vector
      exempleFunction(v);
  }`` 

在这种情况下,函数 swap() 被执行 n-1 次,比前一种情况多 n-2 倍(想象一下如果 n 是 1000000,差异有多大)。但是,exempleFunction 的成本仍然是 O(n)! 同样的事情发生在您的代码中,函数的成本并不代表具体方法将被执行多少次。函数的成本或复杂性是一种衡量基于 n 值执行的指令数量变化的方法。如果您将算法执行的指令数表示为 n 大小的函数,那么您的图表的行为将与您的算法的成本大致相同。

【讨论】:

    猜你喜欢
    • 2015-07-09
    • 1970-01-01
    • 1970-01-01
    • 2013-03-10
    • 1970-01-01
    • 2018-05-30
    • 1970-01-01
    • 2016-10-02
    • 2022-01-09
    相关资源
    最近更新 更多