Quicksort slower than Mergesort?

后端 未结 15 1050
名媛妹妹
名媛妹妹 2021-02-07 02:01

I was working on implementing a quicksort yesterday, and then I ran it, expecting a faster runtime than the Mergesort (which I had also implemented). I ran the two, and while th

相关标签:
15条回答
  • 2021-02-07 02:36

    I ran similar tests and pure quick sort (with random choice of pivot) turned out to be much slower than merge sort for large arrays.

    Choosing the pivot as the median of the first, middle and last element improved quick sort`s performance, but quick sort was still definitely worse than merge sort on large arrays (> 100000 elements).

    I saw a big improvement when I implemented intro-sort, i.e. quick sort that falls back to heap sort if the recursion depth exceeds a certain threshold. My intro-sort implementation was almost as fast as my merge sort implementation. Of course, intro-sort is no longer pure quick sort as it uses heap sort to bring the complexity back to n log(n) when pure quick sort hits some bad data. I can post the results if you are interested.

    0 讨论(0)
  • 2021-02-07 02:37

    This is consistent with the analysis of the algorithms. Merge-sort is guaranteed O(nlogn) for any input and for every runtime. Quicksort is best-case O(nlogn) and average case O(nlogn), but worst-case O(n^2), so the average execution will be in between O(nlogn) and O(n^2).

    Quicksort is the best general case algorithm because it has low overhead, so it has good speed for values of n up to about 10000 or so and still good runtime for arbitrarily astronomical values of n. Merge-sort has the unfortunate overhead of writing a stack frame, required by every recursive call. Thus, for low values of n it has an atrociously high c in RT = cnlogn and it is not the preferred general sorting method.

    Edit: Software Monkey pointed out a contradiction: Quicksort averages O(nlogn) for random input, but O(n^2) worst case. So it actually is somewhat bound by the entropy of your data -- or you could choose the pivot randomly. I might still be off a bit though.

    0 讨论(0)
  • 2021-02-07 02:38

    If you implement heap sort as the base sorting algorithm in quick sorts worst case scenario, you achieve a theta(n log n) algorithm.

    If you don't need stable sorting, and don't sort a linked list, I think that would be the fastest you could go.

    Merge sort

    0 讨论(0)
  • 2021-02-07 02:42

    (1) There is an qsort algo, used by C qsort(), which doesn't require extra memory. This was most probably invented by Hoare. This makes qsort() fast in C.

    (2) Randomizing the data before running qsort will almost always speed it up.

    (3) selecting the median data for pivot may make it faster,

    0 讨论(0)
  • 2021-02-07 02:46

    I think as long as data fits in memory, good merge sort implementation performs better than good quick sort implementation.

    One of the most widely used implementations of qsort(), glibc qsort(), internally uses merge sort for most of the cases when data fits in memory. This merge sort allocates a temporary memory space used for merging, which adds some memory overhead, but most of the time, it outperforms its own internal quicksort implementation with good pivot selection and optimization. glibc only uses quicksort when the data and the temporary memory for merge sort cannot fit in memory.

    I have measured performance of those two implementation on my machine with 2.1GHz CPU with several GB of RAM. The inputs are generated with pseudo-random generator, and each key is 32bit unsigned integer, which means a bit of more comparison cycles than integer comparison due to interface of comparison function.

    For merge sort:

    2 MB, time_diff 165.156000 ms, 78.752518 ns per byte
    4 MB, time_diff 344.298000 ms, 82.087040 ns per byte
    8 MB, time_diff 730.926000 ms, 87.133169 ns per byte
    16 MB, time_diff 1541.215000 ms, 91.863573 ns per byte
    32 MB, time_diff 3088.924000 ms, 92.057109 ns per byte
    64 MB, time_diff 6262.868000 ms, 93.324006 ns per byte
    128 MB, time_diff 12887.018000 ms, 96.015766 ns per byte
    256 MB, time_diff 26731.597000 ms, 99.582959 ns per byte
    

    For quick sort:

    2 MB, time_diff 243.519000 ms, 116.118908 ns per byte
    4 MB, time_diff 504.975000 ms, 120.395422 ns per byte
    8 MB, time_diff 1075.276000 ms, 128.182888 ns per byte
    16 MB, time_diff 2183.865000 ms, 130.168498 ns per byte
    32 MB, time_diff 4343.993000 ms, 129.461080 ns per byte
    64 MB, time_diff 8714.166000 ms, 129.851192 ns per byte
    128 MB, time_diff 17881.344000 ms, 133.226395 ns per byte
    256 MB, time_diff 36751.029000 ms, 136.908252 ns per byte
    

    You can see that there are clear differences in performance between those two implementation and why mergesort is preferred over quicksort in such widely used qsort implementation. The main reason behind this difference seems to be because quick sort has 10-20% more comparisons than merge sort, due to uneven splitting at each step.

    0 讨论(0)
  • 2021-02-07 02:46

    It might depend on what sort of data you're sorting for the testing (already ordered lists, randomized, reverse sorted). Also, quicksort will probably be faster in general if you pick a random pivot instead of using the first element.

    0 讨论(0)
提交回复
热议问题