почему на месте сортировки слияния не является стабильным? - PullRequest
2 голосов
/ 19 декабря 2009

Реализация ниже стабильна, так как она использовала <= вместо < в строке, отмеченной 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);
    }
}

Ответы [ 2 ]

7 голосов
/ 21 декабря 2009

Поскольку <= в вашем коде гарантирует, что одинаковые элементы (в левой и правой половине сортировочного массива) не будут заменены. А также избегает бесполезных обменов.

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") в обеих половинах и оператор выше равен <. Как показывают комментарии выше, правая цифра «5» будет вставлена ​​перед левой цифрой «5», другими словами, будут заменены элементы с одинаковыми значениями. Это означает, что сортировка не является стабильной. А также неэффективно обмениваться элементами с одинаковыми значениями.


Полагаю, причина неэффективности кроется в самом алгоритме. Этап слияния реализован с использованием сортировки вставкой (как вы знаете, это O (n ^ 2)).

Возможно, вам придется заново реализовать, когда вы сортируете огромные массивы.

2 голосов
/ 14 марта 2011

Самый быстроизвестный на месте стабильный сорт:
http://thomas.baudel.name/Visualisation/VisuTri/inplacestablesort.html

...