Implement merging without using an extra array?

I read a lot about mergesort recently, and I wonder if there is a way to make mergesort without using at least one additional array. Is it possible?

+4
source share
4 answers

According to Wikipedia , this is indeed possible, but cannot bring any performance increase:

Sorting in place is possible (for example, using lists rather than arrays), but it is very complicated and in practice will have little performance gain, even if the algorithm runs in O (n log n) time. In such cases, algorithms such as heapsort usually offer comparable speed and are much less complex. In addition, unlike standard merge sorting, in-place merge sorting is not sustainable. In the case of linked lists, the algorithm does not use more space than the one already in use by the list view, but O (log (k)) used to trace the recursion. Some argue that sorting a linked list is absent because, despite the fact that you are sorting in a given data structure, the data structure essentially has O (n) additional data that you are manipulating (e.g.links in the list).

+2

-, . :

. , N log 2 N + O (N) 3N log 2 N + O (N) N . , N log 2 N + O (N) "N log 2 N "? 0 N? N ("). heapsort. - 50 , . mergesort, .

Jyrki Katajainen, Tomi Pasanen, Jukka Teuhola, " " (1996).

+3

Java

public static <T extends Comparable<? super T>> void iterativeMergeSort(T[] seed) {

    for (int i = 1; i <seed.length; i=i+i)
    {
        for (int j = 0; j < seed.length - i; j = j + i+i)
        {
            inPlaceMerge(seed, j, j + i-1, Math.min(j+i + i -1, seed.length -1));
        }
    }       
}
public static <T extends Comparable<? super T>>  void inPlaceMerge(T[] collection, int low, int mid, int high) {
    int left = low;
    int right = mid + 1;

    if(collection[mid].equals(collection[right])) {
        return ;//Skip the merge if required
    }
    while (left <= mid && right <= high) {          
        // Select from left:  no change, just advance left
        if (collection[left].compareTo(collection[right]) <= 0) {
            left ++;
        } else { // Select from right:  rotate [left..right] and correct
            T tmp = collection[right]; // Will move to [left]
            rotateRight(collection, left, right - left);
            collection[left] = tmp;
            // EVERYTHING has moved up by one
            left ++; right ++; mid ++;
        }
    }       
}

unit test

private Integer[] seed;

@Before
public void doBeforeEachTestCase() {
    this.seed = new Integer[]{4,2,3,1,5,8,7,6};
}
@Test
public void iterativeMergeSortFirstTest() {
    ArrayUtils.<Integer>iterativeMergeSort(seed);
    Integer[] result = new Integer[]{1,2,3,4,5,6,7,8};
    assertThat(seed, equalTo(result));  
}
+1

No, you will always need an additional data structure to combine the sorted elements. If not, you are simply rewriting material that you have already sorted.

-2
source

All Articles