合并一个包含2个已排序部分的数组

时间:2015-09-09 00:44:06

标签: algorithm sorting merge

给定一个数组,它有2个部分,每个部分都被排序(例如2 4 6 8 1 3 5),写一个函数使整个数组排序。

要求:

  1. 就位,这意味着O(1)空间复杂性。
  2. 尽可能快。
  3. 很容易写出O(n 2 )或O(n logn)(使用二进制搜索来查找插入位置)解决方案,我想知道是否有可能获得O( n)解决方案?

1 个答案:

答案 0 :(得分:3)

简单的就地合并算法通常会使交换项目冒泡到第二个区域中的正确位置。作为对此的改进,我创建了一个有序的"交换区域"在两个区域之间,新交换项目的位置始终在最后,因此可以更有效地移动到位。

in-place merge with swap zone

我们从两个已排序的区域开始。 (图1)区域1中的项目从左到右逐个地与区域2中的第一个项目进行比较,并在必要时进行交换。一旦区域1中的项目被交换,它就会在区域1和区域2之间创建一个交换区域。(图2)从那时起,区域1中的项目将与第一个项目进行比较。区域2,以及交换区域中的第一个项目。这会产生两种情况:

  • 区域1和2之间的交换:在这种情况下,交换的项目成为交换区域的最后一项;它是交换区域中最大的项目,交换区域保持正确排序。 (图2-3)
  • 区域1和交换区域之间的交换:在这种情况下,交换项目成为交换区域中的第一项;但是,它是交换区域中最大的,因此必须将其移动到交换区域的末尾。 (图3-5)

当区域1完全合并时,交换区域将成为新区域1,算法将再次与阵列的其余部分一起启动。 (图6)



function mergeInPlace(array) {
    var zone2 = 0, swapzone = 0;
    // FIND START OF ZONE 2
    while (array[zone2] <= array[++zone2]);
    // ITERATE OVER ALL ITEMS IN ZONE 1
    for (var zone1 = 0; zone1 < zone2; zone1++) {
        // WHEN ZONE 1 IS SORTED, TREAT SWAP ZONE AS NEW ZONE 1
        if (zone1 == swapzone) swapzone = zone2;
        // CHECK WHETHER SWAP ZONE OR ZONE 2 HAS SMALLEST FIRST ITEM
        if (array[zone2] <= array[swapzone]) {
            // COMPARE AND SWAP WITH FIRST ITEM OF ZONE 2
            if (array[zone1] > array[zone2]) {
                var temp = array[zone1];
                array[zone1] = array[zone2];
                array[zone2++] = temp;
            }
        }
        // COMPARE AND SWAP WITH FIRST ITEM OF SWAP ZONE
        else if (array[zone1] > array[swapzone]) {
            var temp = array[zone1];
            array[zone1] = array[swapzone];
            // MOVE SWAPPED ITEM TO END OF SWAP ZONE
            for (var i = swapzone; i < zone2 - 1; i++) {
                array[i] = array[i + 1];
            }
            array[zone2 - 1] = temp;
        }
    }
}

var a = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,51,1,1,2,3,5,8,13,21,34,55];
mergeInPlace(a);
document.write(a);
&#13;
&#13;
&#13;