<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>porges &#187; sorting</title>
	<atom:link href="http://porg.es/blog/tag/sorting/feed" rel="self" type="application/rss+xml" />
	<link>http://porg.es/blog</link>
	<description></description>
	<lastBuildDate>Sun, 06 May 2012 22:13:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>n-pivot quicksort</title>
		<link>http://porg.es/blog/n-pivot-quicksort</link>
		<comments>http://porg.es/blog/n-pivot-quicksort#comments</comments>
		<pubDate>Sat, 12 Sep 2009 07:56:15 +0000</pubDate>
		<dc:creator>Porges</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[comparison]]></category>
		<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[Haskell]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[quicksort]]></category>
		<category><![CDATA[sorting]]></category>

		<guid isPermaLink="false">http://porg.es/blog/?p=392</guid>
		<description><![CDATA[2-pivot quicksort This posting on the Java core library mailing list proposes to replace the current quicksort with a new, 2-pivot quicksort. Ordinary quicksort in Haskell looks something like this: quicksort &#91;&#93; = &#91;&#93; quicksort &#40;pivot:rest&#41; = quicksort &#91;x&#124; x ← rest, x ≤ pivot&#93; ++ &#91;pivot&#93; ++ quicksort &#91;x&#124; x ← rest, x &#62; [...]]]></description>
			<content:encoded><![CDATA[<h3>2-pivot quicksort</h3>
<p>This <a href="http://permalink.gmane.org/gmane.comp.java.openjdk.core-libs.devel/2628">posting on the Java core library mailing list</a> proposes to replace the current quicksort with a new, 2-pivot quicksort.</p>
<p>Ordinary quicksort in Haskell looks something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="haskell" style="font-family:monospace;">quicksort <span style="color: green;">&#91;</span><span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">=</span> <span style="color: green;">&#91;</span><span style="color: green;">&#93;</span>
quicksort <span style="color: green;">&#40;</span>pivot:rest<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">=</span>
   quicksort <span style="color: green;">&#91;</span>x<span style="color: #339933; font-weight: bold;">|</span> x ← rest<span style="color: #339933; font-weight: bold;">,</span> x ≤ pivot<span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">++</span>
   <span style="color: green;">&#91;</span>pivot<span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">++</span>
   quicksort <span style="color: green;">&#91;</span>x<span style="color: #339933; font-weight: bold;">|</span> x ← rest<span style="color: #339933; font-weight: bold;">,</span> x <span style="color: #339933; font-weight: bold;">&gt;</span> pivot<span style="color: green;">&#93;</span></pre></div></div>

<p>Note the similarity of this to the notation for &#8216;invariants&#8217; used in the email:</p>
<pre>[ <= p | >= p ]</pre>
<p>Similarly, for the 2-pivot invariants (I have corrected a typo in this):</p>
<pre>[ < P1 | P1 <= &#038; <= P2 | > P2 ]</pre>
<p>We can derive the code:</p>

<div class="wp_syntax"><div class="code"><pre class="haskell" style="font-family:monospace;">quicksort2 <span style="color: green;">&#91;</span><span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">=</span> <span style="color: green;">&#91;</span><span style="color: green;">&#93;</span>
quicksort2 <span style="color: green;">&#40;</span>only:<span style="color: green;">&#91;</span><span style="color: green;">&#93;</span><span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">=</span> <span style="color: green;">&#91;</span>only<span style="color: green;">&#93;</span>
quicksort2 <span style="color: green;">&#40;</span>first:second:rest<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">=</span>
   quicksort2 <span style="color: green;">&#91;</span>x<span style="color: #339933; font-weight: bold;">|</span>x ← rest<span style="color: #339933; font-weight: bold;">,</span> x <span style="color: #339933; font-weight: bold;">&lt;</span> p1<span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">++</span>
   <span style="color: green;">&#91;</span>p1<span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">++</span>
   quicksort2 <span style="color: green;">&#91;</span>x<span style="color: #339933; font-weight: bold;">|</span>x ← rest<span style="color: #339933; font-weight: bold;">,</span> p1 ≤ x <span style="color: #339933; font-weight: bold;">&amp;&amp;</span> x ≤ p2<span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">++</span>
   <span style="color: green;">&#91;</span>p2<span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">++</span>
   quicksort2 <span style="color: green;">&#91;</span>x<span style="color: #339933; font-weight: bold;">|</span>x ← rest<span style="color: #339933; font-weight: bold;">,</span> p2 <span style="color: #339933; font-weight: bold;">&lt;</span> x<span style="color: green;">&#93;</span>
  <span style="color: #06c; font-weight: bold;">where</span> <span style="color: green;">&#40;</span>p1<span style="color: #339933; font-weight: bold;">,</span>p2<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">=</span> <span style="color: #06c; font-weight: bold;">if</span> first ≤ second <span style="color: #06c; font-weight: bold;">then</span> <span style="color: green;">&#40;</span>first<span style="color: #339933; font-weight: bold;">,</span>second<span style="color: green;">&#41;</span> <span style="color: #06c; font-weight: bold;">else</span> <span style="color: green;">&#40;</span>second<span style="color: #339933; font-weight: bold;">,</span>first<span style="color: green;">&#41;</span></pre></div></div>

<p>Which does, in fact, run faster than the ordinary 1-pivot quicksort.</p>
<h3><i>n</i>-pivot quicksort</h3>
<p>Of course, this being Haskell we want to take things to their logical conclusions, and allow any number of pivots to be used. My formulation follows:</p>

<div class="wp_syntax"><div class="code"><pre class="haskell" style="font-family:monospace;">quicksortN <span style="color: #339933; font-weight: bold;">_</span> <span style="color: green;">&#91;</span><span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">=</span> <span style="color: green;">&#91;</span><span style="color: green;">&#93;</span>
quicksortN <span style="color: #339933; font-weight: bold;">_</span> <span style="color: green;">&#40;</span>x:<span style="color: green;">&#91;</span><span style="color: green;">&#93;</span><span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">=</span> <span style="color: green;">&#91;</span>x<span style="color: green;">&#93;</span>
quicksortN n xs
    <span style="color: #339933; font-weight: bold;">|</span> n <span style="color: #339933; font-weight: bold;">&gt;</span> <span style="font-weight: bold;">length</span> xs <span style="color: #339933; font-weight: bold;">=</span> quicksortN <span style="color: green;">&#40;</span><span style="color: green;">&#40;</span>n `<span style="font-weight: bold;">div</span>` <span style="color: red;">2</span><span style="color: green;">&#41;</span> `<span style="font-weight: bold;">max</span>` <span style="color: red;">1</span><span style="color: green;">&#41;</span> xs
    <span style="color: #339933; font-weight: bold;">|</span> <span style="font-weight: bold;">otherwise</span> <span style="color: #339933; font-weight: bold;">=</span> part True pivots
    <span style="color: #06c; font-weight: bold;">where</span>
      <span style="color: green;">&#40;</span>takexs<span style="color: #339933; font-weight: bold;">,</span>dropxs<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">=</span> <span style="font-weight: bold;">splitAt</span> n xs
      pivots <span style="color: #339933; font-weight: bold;">=</span> quicksortN <span style="color: red;">1</span> takexs
      part False <span style="color: green;">&#40;</span>p2:<span style="color: green;">&#91;</span><span style="color: green;">&#93;</span><span style="color: green;">&#41;</span>      <span style="color: #339933; font-weight: bold;">=</span> quicksortN n <span style="color: green;">&#91;</span>x<span style="color: #339933; font-weight: bold;">|</span>x ← dropxs<span style="color: #339933; font-weight: bold;">,</span> p2 <span style="color: #339933; font-weight: bold;">&lt;</span> x<span style="color: green;">&#93;</span>
      part False <span style="color: green;">&#40;</span>p1:p2:rest<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">=</span> quicksortN n <span style="color: green;">&#91;</span>x<span style="color: #339933; font-weight: bold;">|</span>x ← dropxs<span style="color: #339933; font-weight: bold;">,</span> p1 <span style="color: #339933; font-weight: bold;">&lt;</span> x <span style="color: #339933; font-weight: bold;">&amp;&amp;</span> x ≤ p2<span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">++</span> <span style="color: green;">&#91;</span>p2<span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">++</span> part False <span style="color: green;">&#40;</span>p2:rest<span style="color: green;">&#41;</span>
      part True  <span style="color: green;">&#40;</span>p1:<span style="color: green;">&#91;</span><span style="color: green;">&#93;</span><span style="color: green;">&#41;</span>      <span style="color: #339933; font-weight: bold;">=</span> quicksortN n <span style="color: green;">&#91;</span>x<span style="color: #339933; font-weight: bold;">|</span>x ← dropxs<span style="color: #339933; font-weight: bold;">,</span> x ≤ p1<span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">++</span> <span style="color: green;">&#91;</span>p1<span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">++</span> quicksortN n <span style="color: green;">&#91;</span>x<span style="color: #339933; font-weight: bold;">|</span>x ← dropxs<span style="color: #339933; font-weight: bold;">,</span> p1 <span style="color: #339933; font-weight: bold;">&lt;</span> x<span style="color: green;">&#93;</span> <span style="color: #5d478b; font-style: italic;">-- remember me? :)</span>
      part True  <span style="color: green;">&#40;</span>p1:p2:rest<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">=</span> quicksortN n <span style="color: green;">&#91;</span>x<span style="color: #339933; font-weight: bold;">|</span>x ← dropxs<span style="color: #339933; font-weight: bold;">,</span> x ≤ p1<span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">++</span> <span style="color: green;">&#91;</span>p1<span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">++</span> part False <span style="color: green;">&#40;</span>p1:p2:rest<span style="color: green;">&#41;</span></pre></div></div>

<p>Now there are only 3 things that I can see that are left &#8216;tweakable&#8217;;</p>
<ul>
<li>how to reduce &#8216;n&#8217; when it is greater than length of the list</p>
<ul>
<li>dividing by 2 here</li>
</ul>
</li>
<li>how to sort the pivots
<ul>
<li>using a recursive call to the 1-pivot version of itself here</li>
</ul>
</li>
<li>whether or not to reduce the number of pivots as sorting continues
<ul>
<li>&#8216;no&#8217; chosen here</li>
</ul>
</li>
</ul>
<p>I have no idea whether these are sensible defaults <img src="http://porg.es/blog/wp-content/plugins/wp-smiley-switcher/noktahhitam/icon_smile.gif" alt="" /></p>
<h3>Which <i>n</i> should I choose?</h3>
<p>Finally, some code for the timings. You&#8217;ll need <a href="http://hackage.haskell.org/package/timeit">timeit</a> to run it.</p>

<div class="wp_syntax"><div class="code"><pre class="haskell" style="font-family:monospace;">main <span style="color: #339933; font-weight: bold;">=</span> <span style="color: #06c; font-weight: bold;">do</span>
 gen ← getStdGen
 <span style="color: #06c; font-weight: bold;">let</span> n <span style="color: #339933; font-weight: bold;">=</span> <span style="color: red;">10</span><span style="color: #339933; font-weight: bold;">^</span><span style="color: red;">6</span>
 <span style="color: #06c; font-weight: bold;">let</span> r <span style="color: #339933; font-weight: bold;">=</span> <span style="font-weight: bold;">take</span> n <span style="color: #339933; font-weight: bold;">$</span> randoms gen <span style="color: #339933; font-weight: bold;">::</span> <span style="color: green;">&#91;</span><span style="color: #cccc00; font-weight: bold;">Int</span><span style="color: green;">&#93;</span>
 <span style="font-weight: bold;">print</span> <span style="color: #339933; font-weight: bold;">$</span> <span style="font-weight: bold;">sum</span> r <span style="color: #5d478b; font-style: italic;">-- force list</span>
 timeIt <span style="color: #339933; font-weight: bold;">.</span> <span style="font-weight: bold;">putStrLn</span> <span style="color: #339933; font-weight: bold;">.</span> <span style="color: green;">&#40;</span><span style="background-color: #3cb371;">&quot;quicksort = &quot;</span><span style="color: #339933; font-weight: bold;">++</span><span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">.</span> <span style="font-weight: bold;">show</span> <span style="color: #339933; font-weight: bold;">.</span> <span style="font-weight: bold;">sum</span> <span style="color: #339933; font-weight: bold;">$</span> quicksort r
 timeIt <span style="color: #339933; font-weight: bold;">.</span> <span style="font-weight: bold;">putStrLn</span> <span style="color: #339933; font-weight: bold;">.</span> <span style="color: green;">&#40;</span><span style="background-color: #3cb371;">&quot;quicksort2 = &quot;</span><span style="color: #339933; font-weight: bold;">++</span><span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">.</span> <span style="font-weight: bold;">show</span> <span style="color: #339933; font-weight: bold;">.</span> <span style="font-weight: bold;">sum</span> <span style="color: #339933; font-weight: bold;">$</span> quicksort2 r
 <span style="font-weight: bold;">mapM_</span> <span style="color: green;">&#40;</span>\x → timeIt <span style="color: #339933; font-weight: bold;">.</span> <span style="font-weight: bold;">putStrLn</span> <span style="color: #339933; font-weight: bold;">.</span> <span style="color: green;">&#40;</span><span style="color: green;">&#40;</span><span style="background-color: #3cb371;">&quot;quicksortN &quot;</span><span style="color: #339933; font-weight: bold;">++</span> <span style="font-weight: bold;">show</span> x<span style="color: #339933; font-weight: bold;">++</span><span style="background-color: #3cb371;">&quot; = &quot;</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">++</span><span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">.</span> <span style="font-weight: bold;">show</span> <span style="color: #339933; font-weight: bold;">.</span> <span style="font-weight: bold;">sum</span> <span style="color: #339933; font-weight: bold;">$</span> quicksortN x r<span style="color: green;">&#41;</span>
    <span style="color: green;">&#91;</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">..</span><span style="color: red;">20</span><span style="color: green;">&#93;</span></pre></div></div>

<p>Sample output:</p>
<pre>$ ./sort
858124546
quicksort = 858124546
CPU time:   4.60s
quicksort2 = 858124546
CPU time:   3.66s
quicksortN 1 = 858124546
CPU time:   5.19s
quicksortN 2 = 858124546
CPU time:   3.77s
quicksortN 3 = 858124546
CPU time:   3.28s
quicksortN 4 = 858124546
CPU time:   3.27s
quicksortN 5 = 858124546
CPU time:   3.06s
quicksortN 6 = 858124546
CPU time:   3.04s
quicksortN 7 = 858124546
CPU time:   3.04s
quicksortN 8 = 858124546
CPU time:   3.07s
quicksortN 9 = 858124546
CPU time:   3.10s
quicksortN 10 = 858124546
CPU time:   3.14s
quicksortN 11 = 858124546
CPU time:   3.22s
quicksortN 12 = 858124546
CPU time:   3.31s
quicksortN 13 = 858124546
CPU time:   3.30s
quicksortN 14 = 858124546
CPU time:   3.37s
quicksortN 15 = 858124546
CPU time:   3.54s
quicksortN 16 = 858124546
CPU time:   3.41s
quicksortN 17 = 858124546
CPU time:   3.52s
quicksortN 18 = 858124546
CPU time:   3.65s
quicksortN 19 = 858124546
CPU time:   3.63s
quicksortN 20 = 858124546
CPU time:   3.77s
</pre>
<p>As expected, generalized quicksort performs slower than the equivalent hard-coded quicksorts for specific values of <i>n</i>, but higher values of <i>n</i> than 1 or 2 can perform better.</p>
]]></content:encoded>
			<wfw:commentRss>http://porg.es/blog/n-pivot-quicksort/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

