【问题标题】:merge sort performance compared to insertion sort与插入排序相比的合并排序性能
【发布时间】:2017-07-24 23:18:56
【问题描述】:

对于任何长度大于 10 的数组,是否可以肯定地说,合并排序在数组元素之间执行的比较比对同一数组的插入排序执行的比较少,因为合并排序运行时间的最佳情况是 O(N log N) 而对于插入排序,它的 O(N)?

【问题讨论】:

  • 这不是 java 问题。此外,插入排序是 O(n^2) 最坏的情况。请编辑。
  • big O 不包括常量,因此您在比较 K1*N*log(K2*N)+K3K4*N+K5

标签: mergesort insertion-sort


【解决方案1】:

我对此的看法。首先,您在谈论比较,但也有交换。

在最坏情况下的插入排序(以相反方向排序的数组)你必须做n^2 - n 比较和交换(11^2 - 11 = 121 - 11 = 110 11 个元素 , 例如)。但是,如果数组甚至按需要的顺序部分排序(我的意思是许多元素已经停留在正确的位置,甚至离它们不远),交换和比较的数量可能会显着下降。很快就会找到元素的正确位置,并且不需要执行与以相反顺序排序的数组一样多的操作。因此,正如您所见,arr2 几乎已排序,动作的数量将变为线性(与输入大小相关) - 6

var arr1 = [11,10,9,8,7,6,5,4,3,2,1];
var arr2 = [1,2,3,4,5,6,7,8,11,10,9];

function InsertionSort(arr) {
    var arr = arr, compNum = 0, swapNum = 0;
    for(var i = 1; i < arr.length; i++) {
        var temp = arr[i], j = i - 1;
        while(j >= 0) {
            if(temp < arr[j]) { arr[j + 1] = arr[j]; swapNum++; } else break;
            j--;
            compNum++;
        }
        arr[j + 1] = temp;
    }
    console.log(arr, "Number of comparisons: " + compNum, "Number of swaps: " + swapNum);
}
InsertionSort(arr1); // worst case, 11^2 - 11 = 110 actions
InsertionSort(arr2); // almost sorted array, few actions

在归并排序中,我们总是做 aprox。 n*log n 动作 - 输入数组的属性无关紧要。因此,正如您在这两种情况下看到的那样,我们将把两个数组按 39 个动作排序

var arr1 = [11,10,9,8,7,6,5,4,3,2,1];
var arr2 = [1,2,3,4,5,6,7,8,11,10,9];
var actions = 0;
function mergesort(arr, left, right) {
  if(left >= right) return;
  var middle = Math.floor((left + right)/2);
  mergesort(arr, left, middle);
  mergesort(arr, middle + 1, right);
  merge(arr, left, middle, right);
}
function merge(arr, left, middle, right) {
  var l = middle - left + 1, r = right - middle, temp_l = [], temp_r = [];
  for(var i = 0; i < l; i++) temp_l[i] = arr[left + i];
  for(var i = 0; i < r; i++) temp_r[i] = arr[middle + i + 1];
  var i = 0, j = 0, k = left;
  while(i < l && j < r) {
    if(temp_l[i] <= temp_r[j]) {
    arr[k] = temp_l[i]; i++;
    } else {
    arr[k] = temp_r[j]; j++;  
    }
  k++; actions++; 
  }
  while(i < l) { arr[k] = temp_l[i]; i++; k++; actions++;}
  while(j < r) { arr[k] = temp_r[j]; j++; k++; actions++;}
}
mergesort(arr1, 0, arr1.length - 1);
console.log(arr1, "Number of actions: " + actions); // 11*log11 = 39 (aprox.)
actions = 0;
mergesort(arr2, 0, arr2.length - 1);
console.log(arr2, "Number of actions: " + actions); // 11*log11 = 39 (aprox.)

所以,回答你的问题:

对于任何长度大于 10 的数组,是否可以肯定地说,合并排序在数组元素之间执行的比较比对同一数组的插入排序执行的比较少

我会说不,这样说是不安全的。在某些情况下,与插入排序相比,合并排序可以执行更多操作。数组的大小在这里并不重要。在比较插入排序与合并排序的这种特殊情况下,重要的是您的数组离排序状态有多远。希望对你有帮助:)

顺便说一句,归并排序和插入排序已经结合在一个称为Timsort 的混合稳定排序算法中,以充分利用它们。有兴趣可以看看。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-01
    • 2018-03-08
    • 2021-11-03
    • 2021-02-03
    • 1970-01-01
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多