Skip to main content
Code Review

Return to Question

Fix QuickMergesort official case + fix typo
Source Link
Morwenn
  • 20.2k
  • 3
  • 69
  • 132

QuickMergeSort QuickMergesort — The power of internal buffering

QuickMergeSortQuickMergesort

QuickMergeSortQuickMergesort applies a partition just like quicksort on the whole sequence, then applies mergesort as follows:

A new flavour of QuickMergeSortQuickMergesort

Instead of partitioning the original sequence with a usual median-of-three pivot selection, I decided that I could use std::nth_element instead for the partition step, always choosing a pivot that splits the sequence to sort into two partitions whose sizes are respectively two thirds and one third of the size of the partition to sort. That way, it ensures that mergesort can be performerdperformed on the biggest possible partition at each step.

QuickMergeSort — The power of internal buffering

QuickMergeSort

QuickMergeSort applies a partition just like quicksort on the whole sequence, then applies mergesort as follows:

A new flavour of QuickMergeSort

Instead of partitioning the original sequence with a usual median-of-three pivot selection, I decided that I could use std::nth_element instead for the partition step, always choosing a pivot that splits the sequence to sort into two partitions whose sizes are respectively two thirds and one third of the size of the partition to sort. That way, it ensures that mergesort can be performerd on the biggest possible partition at each step.

QuickMergesort — The power of internal buffering

QuickMergesort

QuickMergesort applies a partition just like quicksort on the whole sequence, then applies mergesort as follows:

A new flavour of QuickMergesort

Instead of partitioning the original sequence with a usual median-of-three pivot selection, I decided that I could use std::nth_element instead for the partition step, always choosing a pivot that splits the sequence to sort into two partitions whose sizes are respectively two thirds and one third of the size of the partition to sort. That way, it ensures that mergesort can be performed on the biggest possible partition at each step.

It uses log n space due to recursion, not n log n
Source Link
Morwenn
  • 20.2k
  • 3
  • 69
  • 132

std::nth_element runs in \$\mathcal{O}(n)\$, and top-down mergesort in \$\mathcal{O}(n \log{n})\$. To be honest, I don't know whether the whole thing actually runs in \$\mathcal{O}(n \log{n})\$ or in \$\mathcal{O}(n \log^{2}{n})\$. I'd say \$\mathcal{O}(n \log{n})\$, but then again I'm not sure. Since I choose to use a top-down mergesort for the sake of simplicity, the algorithm takes \$\mathcal{O}(n \log{n})\$\$\mathcal{O}(\log{n})\$ space, but it could use \$\mathcal{O}(1)\$ space with a bottom-up mergesort.

std::nth_element runs in \$\mathcal{O}(n)\$, and top-down mergesort in \$\mathcal{O}(n \log{n})\$. To be honest, I don't know whether the whole thing actually runs in \$\mathcal{O}(n \log{n})\$ or in \$\mathcal{O}(n \log^{2}{n})\$. I'd say \$\mathcal{O}(n \log{n})\$, but then again I'm not sure. Since I choose to use a top-down mergesort for the sake of simplicity, the algorithm takes \$\mathcal{O}(n \log{n})\$ space, but it could use \$\mathcal{O}(1)\$ space with a bottom-up mergesort.

std::nth_element runs in \$\mathcal{O}(n)\$, and top-down mergesort in \$\mathcal{O}(n \log{n})\$. To be honest, I don't know whether the whole thing actually runs in \$\mathcal{O}(n \log{n})\$ or in \$\mathcal{O}(n \log^{2}{n})\$. I'd say \$\mathcal{O}(n \log{n})\$, but then again I'm not sure. Since I choose to use a top-down mergesort for the sake of simplicity, the algorithm takes \$\mathcal{O}(\log{n})\$ space, but it could use \$\mathcal{O}(1)\$ space with a bottom-up mergesort.

Improve MathJax
Source Link
Morwenn
  • 20.2k
  • 3
  • 69
  • 132

std::nth_element runs in O(n)\$\mathcal{O}(n)\$, and top-down mergesort in \$\mathcal{O}(n * log(n))\$\$\mathcal{O}(n \log{n})\$. To be honest, I don't know whether the whole thing actually runs in \$\mathcal{O}(n * log(n))\$\$\mathcal{O}(n \log{n})\$ or in \$\mathcal{O}(n * log^2(n))\$\$\mathcal{O}(n \log^{2}{n})\$. I'd say \$\mathcal{O}(n * log(n))\$\$\mathcal{O}(n \log{n})\$, but then again I'm not sure. Since I choose to use a top-down mergesort for the sake of simplicity, the algorithm takes \$\mathcal{O}(n * log(n))\$\$\mathcal{O}(n \log{n})\$ space, but it could use \$\mathcal{O}(1)\$ space with a bottom-up mergesort.

I think that the algorithm is quite elegant and rather fast without being too clever for its own good, and a is pretty good example of what can be done with internal buffering without being as complex as a block sort. It also allowed me to finally find a good use for std::nth_element (I was pretty disappointed by the speed of the \$\mathcal{O}(n * log(n))\$\$\mathcal{O}(n \log{n})\$ quicksort that uses std::nth_element for its partitioning step), which is also quite nice :)

std::nth_element runs in O(n), and top-down mergesort in \$\mathcal{O}(n * log(n))\$. To be honest, I don't know whether the whole thing actually runs in \$\mathcal{O}(n * log(n))\$ or in \$\mathcal{O}(n * log^2(n))\$. I'd say \$\mathcal{O}(n * log(n))\$, but then again I'm not sure. Since I choose to use a top-down mergesort for the sake of simplicity, the algorithm takes \$\mathcal{O}(n * log(n))\$ space, but it could use \$\mathcal{O}(1)\$ space with a bottom-up mergesort.

I think that the algorithm is quite elegant and rather fast without being too clever for its own good, and a is pretty good example of what can be done with internal buffering without being as complex as a block sort. It also allowed me to finally find a good use for std::nth_element (I was pretty disappointed by the speed of the \$\mathcal{O}(n * log(n))\$ quicksort that uses std::nth_element for its partitioning step), which is also quite nice :)

std::nth_element runs in \$\mathcal{O}(n)\$, and top-down mergesort in \$\mathcal{O}(n \log{n})\$. To be honest, I don't know whether the whole thing actually runs in \$\mathcal{O}(n \log{n})\$ or in \$\mathcal{O}(n \log^{2}{n})\$. I'd say \$\mathcal{O}(n \log{n})\$, but then again I'm not sure. Since I choose to use a top-down mergesort for the sake of simplicity, the algorithm takes \$\mathcal{O}(n \log{n})\$ space, but it could use \$\mathcal{O}(1)\$ space with a bottom-up mergesort.

I think that the algorithm is quite elegant and rather fast without being too clever for its own good, and a is pretty good example of what can be done with internal buffering without being as complex as a block sort. It also allowed me to finally find a good use for std::nth_element (I was pretty disappointed by the speed of the \$\mathcal{O}(n \log{n})\$ quicksort that uses std::nth_element for its partitioning step), which is also quite nice :)

added 129 characters in body
Source Link
Grajdeanu Alex
  • 9.3k
  • 4
  • 32
  • 71
Loading
algorithm -> sequence
Source Link
Morwenn
  • 20.2k
  • 3
  • 69
  • 132
Loading
Mention that QuickXsort algorithms are unstable
Source Link
Morwenn
  • 20.2k
  • 3
  • 69
  • 132
Loading
Tweeted twitter.com/StackCodeReview/status/807325723946090496
Source Link
Morwenn
  • 20.2k
  • 3
  • 69
  • 132
Loading
lang-cpp

AltStyle によって変換されたページ (->オリジナル) /