【问题标题】:why is in place merge sort not stable?为什么就地合并排序不稳定?
【发布时间】:2009-12-19 18:56:33
【问题描述】:

下面的实现是稳定的,因为它在标记为 XXX 的行使用了<= 而不是<。这也使它更有效率。有什么理由在这一行使用< 而不是<=

/**
class for In place MergeSort
**/
class MergeSortAlgorithm extends SortAlgorithm {
    void sort(int a[], int lo0, int hi0) throws Exception {
    int lo = lo0;
    int hi = hi0;
    pause(lo, hi);
    if (lo >= hi) {
        return;
    }
    int mid = (lo + hi) / 2;

        /*
         *  Partition the list into two lists and sort them recursively
         */
        sort(a, lo, mid);
        sort(a, mid + 1, hi);

        /*
         *  Merge the two sorted lists
         */
    int end_lo = mid;
        int start_hi = mid + 1;
    while ((lo <= end_lo) && (start_hi <= hi)) {
            pause(lo);
        if (stopRequested) {
                return;
            }
            if (a[lo] <= a[start_hi]) {                   // LINE XXX
                lo++;
            } else {
                /*  
                 *  a[lo] >= a[start_hi]
                 *  The next element comes from the second list, 
                 *  move the a[start_hi] element into the next 
                 *  position and shuffle all the other elements up.
                 */
        int T = a[start_hi];
                for (int k = start_hi - 1; k >= lo; k--) {
                    a[k+1] = a[k];
                    pause(lo);
                }
                a[lo] = T;
                lo++;
                end_lo++;
                start_hi++;
            }
        }
    }

    void sort(int a[])  throws Exception {
    sort(a, 0, a.length-1);
    }
}

【问题讨论】:

  • 不,没有理由。对已经排序的值进行排序是没有意义的。

标签: java sorting mergesort in-place


【解决方案1】:

因为您的代码中的&lt;= 确保不会交换相同值的元素(在排序数组的左半部分和右半部分)。 而且,它避免了无用的交换。

if (a[lo] <= a[start_hi]) {
 /* The left value is smaller than or equal to the right one, leave them as is. */
 /* Especially, if the values are same, they won't be exchanged. */
 lo++;
} else {
 /*
  * If the value in right-half is greater than that in left-half,
  * insert the right one into just before the left one, i.e., they're exchanged.
  */
 ...
}

假设两半中的相同值元素(例如,'5')并且上面的运算符是&lt;。 如上面的 cmets 所示,右边的 ‘5’ 将被插入到左边的 ‘5’ 之前,也就是说,相同值的元素将被交换。 这意味着排序不稳定。 而且,交换相同值的元素效率很低。


我猜效率低下的原因来自算法本身。 您的合并阶段是使用插入排序实现的(如您所知,它是 O(n^2))。

当你对大数组进行排序时,你可能需要重新实现。

【讨论】:

  • +1 是的,合并实际上可以在 O(n) 中完成,仅在小数组(例如少于 7 个元素)上,插入排序优于 mergeSort,因为它的常数因子很小。
【解决方案2】:

【讨论】:

    猜你喜欢
    • 2013-10-20
    • 2020-12-28
    • 1970-01-01
    • 1970-01-01
    • 2011-04-01
    • 2011-08-22
    • 1970-01-01
    • 2012-01-03
    • 2021-12-09
    相关资源
    最近更新 更多