当数组长度是偶数时,在mergesort合并函数中应该做什么,特别是在size = 2的情况下?

时间:2016-04-27 09:38:12

标签: algorithm sorting mergesort

我已经实现了mergesort合并功能,但是虽然我尽可能地复制了它,但是当左,中,右参数为0,0,1时,我遇到了问题。在这种情况下,逻辑似乎完全毁了。当输入数组14,7时,它输出14,7。原因是左= =中,所以它会立即插入。

这里的mergesort函数传递了测试用例,但它只调试了合并函数。

我原以为0,0,1是一个无效的参数规范,但是没有,没有其他方法可以在length = 2数组中传递中间元素。

我尝试将代码基于https://www.cs.cmu.edu/~adamchik/15-121/lectures/Sorting%20Algorithms/code/MergeSort.java

// Takes in an array that has two sorted subarrays,
//  from [p..q] and [q+1..r], and merges the array
var merge = function(array, p, q, r) {
  console.log(array);
  console.log(p);
  console.log(q);
  console.log(r);
  var tmp = {};
  var k = p;
  var middle = q;
  while(p<=middle && q <= r){
    console.log("aaa");
    console.log(array[p]);
    console.log(array[q]);
    console.log("bbb");

    if (array[p] < array[q]){
        tmp[k] = array[p];
        k++;
        p++;
    } else {
        tmp[k] = array[q];
        k++;
        q++;
    }
  }
  while(p<middle){
        //tmp[k] = array[p];
        k++;
    p++;
  }
  while(r >= q){
        //tmp[k] = array[q];
        k++;
    q++;
  }

  for(var i in tmp){
    array[i] = tmp[i];
  }
  console.log(array);
  console.log(tmp);
  console.log("test");
};


// Takes in an array and recursively merge sorts it
var mergeSort = function(array, p, r) {
    var lowerIndex = p;
    var higherIndex = r;
            if (lowerIndex < higherIndex) {
            var middle = Math.floor(lowerIndex + (higherIndex - lowerIndex) / 2);
            // Below step sorts the left side of the array
            mergeSort(array,lowerIndex, middle);
            // Below step sorts the right side of the array
            mergeSort(array,middle + 1, higherIndex);
            // Now merge both sides
            merge(array,lowerIndex, middle, higherIndex);
        }
};

var array = [14, 7, 3, 12, 9, 11, 6, 2];
array = [14, 7];
mergeSort(array, 0, array.length-1);
console.log("Array after sorting: " + array);
//Program.assertEqual(array, [2, 3, 6, 7, 9, 11, 12, 14]);

2 个答案:

答案 0 :(得分:2)

中间索引必须只属于其中一个范围。目前,您正在使用<=进行比较,因此它属于两者。

在我看来,使用表达范围的更常见约定作为第一个索引是值和第一个无效的索引会更容易混淆。您输入的0,0,1表示第一个索引的范围超过 [0,0] ,而第二个索引的范围超过 [0,1] 。因此,在某些时候,您将array[0]处的数据与自身进行比较,然后将其添加到输出列表中。使中间点和终点独占意味着范围 [0,1) [1,2)的输入是明确的。 (在一个范围内,圆括号表示独占)

答案 1 :(得分:2)

在您的命名法中,数组边界是包含的:下限是范围的第一个元素,上限是范围的最后一个元素。 mid元素是左子数组的最后一个元素,因此,正确的数组以mid + 1开头,您可以在调用中看到:

        mergeSort(array, lowerIndex, middle);        // sort left array
        mergeSort(array, middle + 1, higherIndex);   // sot right array

但是在merge中,您将mid分配到正确的范围:索引q应该从中间的一个元素开始。 (另外,你不一致地使用限制:在第一个循环中,从pq中选择smalles元素,你测试p<=middle,这与你的命名法一致,后来你使用p<middle

这是您更正的merge功能:

       var merge = function(array, p, middle, r) {
          console.log(p, q, r);
          var tmp = {};
          var k = p;
          var q = middle + 1;

          while(p <= middle && q <= r){
            if (array[p] < array[q]){
                tmp[k++] = array[p++];
            } else {
                tmp[k++] = array[q++];
            }
          }

          while(p <= middle) tmp[k++] = array[p++];
          while(q <= r) tmp[k++] = array[q++];

          for(var i in tmp) array[i] = tmp[i];
        }

我是第二个Pete建议使用独占上限。在这个术语中,子阵列为array[lo:mid]array[mid:hi],因为midhi的初始值为array.length,不属于范围。< / p>