basePARTICLE said:
Here is a link that describes sorting results between the merge sort and the quick sort, differently from how you did. http://www.atkinson.yorku.ca/~sychen/ITEC2620/Sorting/nlognSorting.html" . This is a java demonstration. You can basically trust the results, I believe. I worked at that University, twenty years ago (not a real reason, but...).
The merge sort demo at that website uses the same inefficient algorithm that wikipedia and so many other web sites describes as a "merge sort", one of my pet peeves. It's a "top down" "divide and conquer" algorithm that is significantly different than a "classic" merge sort, which is now called a "bottom up" merge sort. I've added comments to the wikipedia article in the discussion section about this. You have to do a web search for "bottom up merge sort" to easily find references to the classic version of a merge sort.
Here is a link to a website that includes an animation of a "bottom up" merge sort as well as the other types of sorts.
http://www.csc.depauw.edu/~bhoward/courses/0304Fall/csc222/sort
A "bottom up" merge sort normally consists of two phases. A makegroups phase where some algorithim is used to create the initial groups of elements, and then a mergegroup phase where the initial groups are repeatedly merged until there is only a single group of elements. A "natural" "bottom up" merge sort looks for sequential sequences of ascending or decending elements during the makegroups phase, decending elements are handled by reversing the pointers or indexes to elements, or decending groups are handled during the first merge pass, especially if sorting data directly. A simple makegroups function could create groups of 2 elements, swapping elements (or pointers) if not ascending. Simpler still is no makegroups phase, and just starting of with groups of 1 element each. The overhead for a "natural" merge sort is that the variable group sizes require an additional array of counts for the number of elements in each group, but note that the size of this array of counts is cut in half on each merge sort pass, so it's only a significant overhead on the early merge passes when there are a relatively large number of small groups.
I have a "natural" makegroups as an option in the text sort routines. If the define for VARSZGRP is set to 1, the "natural" version of makegroups is used, and if it's set to 0, then the create groups of 2 elements version of makegroups is used.
A top down "merge sort" first recursively divides data into smaller and smaller groups until it's gets down to groups of 2 or less, or to less than some fixed size where it uses some other sort algorithm, before it actually begins a true merge sort.
In the animated case from the link above, the "bottom up" merge starts off with group size = 1 (no makegroups phase). The "benchmark" is based on the number of operations, and based on it's "operations" count, quicksort is much faster than bottom up merge sort on random data, but my actual testing shows the cpu usage to be close when sorting random data (the sort data directly merge sort was about 15% slower than quicksort in 64bit mode, with less difference in 32 bit mode), but the merge sort was faster when using pointers or indexes.
The main reason "top down" merge sort is shown on so many web sites is that its an inplace sort algorithm, similar to other "divide and conquer" sort algorithms used. A "bottom up" merge sort requires double the amount of memory for the list of pointers or indexes to elements, or worse yet, double the data space if directly sorting elements. Perhaps the "bottom up" merge sort is considered "unfair" since it uses "double the memory". In addition, a "natural" "bottom up" merge sort will require an additional array to keep track of the element count for all the groups created during the make groups phase, since the group sizes will be variable based on the amount of pre-ordering in a file.
One of the major shortcomings of a "top down" merge sort is that it can't directly take advantage of any natural ordering. In addition, the recursive nature adds overhead with all the indexes that get pushed and popped on and off the stack. It's almost doing double the work of of a normal "bottom up" merge sort.
The classic, now called "bottom up" merge sort was a tape sort using 4 tape drives, using all sequential I/O. (3 is the actual minimum but it requires double the number of passes). One reason for using tape drives is that with multiple heads reading and writing in parallel, they could transfer streaming data faster than disk drives. The same is true today, but the fast tape drives cost $5500 or more, so it's not worth it when compared to a raid of hard drives, since hard drives are so relatively cheap these days.
If you look at the benchmark data from thread I linked to before, the trade off is that quicksort does more compares, but moves less data. This is helpful if the sort is actually sorting data, but in the case of pointer or indexed based sorting, the comparason overhead is generally higher than the movement of pointers, at least in the case where the element size and number of elements is large, and elements are similar enough that comparasons of pairs of elements have to compare a significant amount of data before detecting a difference.
Sorry if I'm a little rusty, but how does someone know if the data has any significant pre-ordering, so use can be made of a particular sort object? In my time, O(rder) = N*log(N) was an indication of sorting prowess.
A "natural" merge sort, auto detects this, during the makegroups phase. If the data is already sorted, it does N-1 compares and moves no data, O = N-1 in this case.
My claim is I will linearily speed up that qs() with my in-line sorting of less than five elements, at the average cost of one if computation.
I'm not sure about this, since it wasn't done in the quick sort that is part of the standard template library (at least the one from Visual Studio). If you have Visual Studio (note that Visual Studio Express is a free downloadable tool from Microsoft), you can look at the code in the template include file.
...\Microsoft Visual Studio 8\VC\include\algorithm
sort() is a quicksort, and doesn't change it's method based on node size unless it decides there are too many nodes (bad mid-value guess), and switches to a heap sort for the problem nodes.
stable_sort() is a standard bottom up merge sort, and does use insertion sort to create groups of 32 elements in it's makegroups phase before beginning the actual sort. I didn't bother, but since "algorithm" is a source file, the 32 is an easily changed value.
Since this is a standard template "library", and based on the comments at the end of the source file, it appears that these are generic C++ standard algorithms as oppposed to Microsoft specific algorithms, although Microsoft may have made some tweaks to the algorithms. I don't know if "algorithms" is include as a part of the "standard template library" for non-Microsoft C++ compliers.
(After a bazillion edits to this, I think I'm finally done with this post).