How is shell sort algorithm any better than of merge sort algorithm? How is shell sort algorithm any better than of merge sort algorithm? shell shell

How is shell sort algorithm any better than of merge sort algorithm?


You have to remember the context in which shellsort was proposed: shellsort was published in 1959; quicksort, in 1961; mergesort, in 1948 (OK, that was a bit surprising). The computers of the day were slow and had small memories. Thus the asymptotic advantage of mergesort was hardly relevant compared to the increased complexity of implemention and code. In fact, shellsort gets the quadratic fallback of modern practical mergesorts for free, since insertion sorting with a gap of 1 is insertion sort.

It was not known then how to do an efficient in-place merge (and even now, no one implements it, because it's wildly inefficient in practice).

Shellsort has an uncomplicated nonrecursive implementation. Recursion in higher-level languages was confined to LISP (impractical then, not to mention lacking an array type) and the as-yet unimplemented ALGOL 60 standard.

Shellsort's running time improves a lot on mostly sorted data. (It's no Timsort though.)


Merge sort is normally faster than shell sort, but shell sort is in place. Quick sort is faster if sorting data, but merge sort is usually faster if sorting an array of pointers or indices to data, if the compare overhead for the elements is greater than the move overhead for pointers or indices, since merge sort uses fewer compares but more moves than quick sort. If sorting an array of somewhat random integers, then counting / radix sort is fastest.

As mentioned, merge sort was published in 1948. Merge sort on old mainframes was implemented on tape drivers or disk drives. For tape drives, there were/are variations of merge sort:

http://en.wikipedia.org/wiki/Polyphase_merge_sort

http://en.wikipedia.org/wiki/Oscillating_merge_sort

Natural merge sort takes advantages of any existing natural ordering, but has the overhead of keeping track of variable size runs. With tape drives, this can/could be done using single file marks for end of runs, double file marks for end of data. Early disk drives with variable sized blocks could implement something similar (using small blocks to indicate end of run / end of data).

http://en.wikipedia.org/wiki/Merge_sort#Natural_merge_sort

An alternative to natural merge sort is tim sort, where natural and/or forced ordering using insertion sort is used to create runs of fixed size during the initial pass:

http://en.wikipedia.org/wiki/Timsort

The "classic" merge sort is bottom up merge sort, and in the case of an external sort, using tape drives or disk drives, the initial pass sorts data in memory, to skip past the initial merge passes, similar to tim sort, except that the memory sort may not have been insertion sort, and generally an array of pointers or indices were sorted, and the data written according to those pointers or indices, as opposed to sorting data in memory before writing. On some systems, a single I/O with multiple pointers / lengths to data is/was used. SATA / IDE / SCSI PC controllers have a set of descriptors that hold address / length data to deal with paged memory, but I don't know if any high end sort programs for PC's use the descriptors to write a set of records for merge sort with a single I/O.

I'm not sure when top down merge sort was first published. Rather than starting off with some fixed or variable run size and using iteration to advance indices or pointers while merging runs, it recursively generates indices or pointers until they represent some small fixed run size, typically a run size of 1, and only then does any actual merging of data take place. Whatever advantage there might be due to cache localization of a depth first / left first ordering of run merges, it is offset by the overhead of recursion, and generally top down merge sort is slightly slower (about 5%) than bottom up merge sort).


It depends on your definition of "better", but if you look at a commonly used metric - worst case performance - merge sort (O(n log n)) is actually faster for large lists than shell sort (O(n^2)).

In terms of space complexity, both can be implemented in-place, so there's no advantage here for shell sort either.