<?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>purpose algorithm &#8211; stoimen&#039;s web log</title>
	<atom:link href="/tag/purpose-algorithm/feed/" rel="self" type="application/rss+xml" />
	<link></link>
	<description>on web development</description>
	<lastBuildDate>Tue, 13 Feb 2018 08:18:15 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.0.3</generator>
	<item>
		<title>Computer Algorithms: Strassen&#8217;s Matrix Multiplication</title>
		<link>/2012/11/26/computer-algorithms-strassens-matrix-multiplication/</link>
		<comments>/2012/11/26/computer-algorithms-strassens-matrix-multiplication/#comments</comments>
		<pubDate>Mon, 26 Nov 2012 14:16:51 +0000</pubDate>
		<dc:creator><![CDATA[Stoimen]]></dc:creator>
				<category><![CDATA[algorithms]]></category>
		<category><![CDATA[Algebra]]></category>
		<category><![CDATA[Binary operations]]></category>
		<category><![CDATA[Coppersmith–Winograd algorithm]]></category>
		<category><![CDATA[Divide and conquer algorithm]]></category>
		<category><![CDATA[faster solution]]></category>
		<category><![CDATA[final solution]]></category>
		<category><![CDATA[given solution]]></category>
		<category><![CDATA[graph algorithms]]></category>
		<category><![CDATA[Linear algebra]]></category>
		<category><![CDATA[mathematician]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Matrix]]></category>
		<category><![CDATA[matrix multiplication algorithm]]></category>
		<category><![CDATA[Matrix theory]]></category>
		<category><![CDATA[Multiplication]]></category>
		<category><![CDATA[Multiplication algorithm]]></category>
		<category><![CDATA[n^3 algorithm]]></category>
		<category><![CDATA[n^3 matrix multiplication algorithm]]></category>
		<category><![CDATA[Numerical linear algebra]]></category>
		<category><![CDATA[NxN]]></category>
		<category><![CDATA[Operations research]]></category>
		<category><![CDATA[purpose algorithm]]></category>
		<category><![CDATA[sort algorithm]]></category>
		<category><![CDATA[sub-solutions]]></category>
		<category><![CDATA[Volker Strassen]]></category>

		<guid isPermaLink="false">/?p=3466</guid>
		<description><![CDATA[Introduction The Strassen’s method of matrix multiplication is a typical divide and conquer algorithm. We’ve seen so far some divide and conquer algorithms like merge sort and the Karatsuba’s fast multiplication of large numbers. However let’s get again on what’s behind the divide and conquer approach. Unlike the dynamic programming where we “expand” the solutions &#8230; <a href="/2012/11/26/computer-algorithms-strassens-matrix-multiplication/" class="more-link">Continue reading <span class="screen-reader-text">Computer Algorithms: Strassen&#8217;s Matrix Multiplication</span> <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>

Related posts:<ol>
<li><a href="/2013/01/14/computer-algorithms-multiplication/" rel="bookmark" title="Computer Algorithms: Multiplication">Computer Algorithms: Multiplication </a></li>
<li><a href="/2012/05/15/computer-algorithms-karatsuba-fast-multiplication/" rel="bookmark" title="Computer Algorithms: Karatsuba Fast Multiplication">Computer Algorithms: Karatsuba Fast Multiplication </a></li>
<li><a href="/2012/10/22/computer-algorithms-bellman-ford-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Bellman-Ford Shortest Path in a Graph">Computer Algorithms: Bellman-Ford Shortest Path in a Graph </a></li>
<li><a href="/2012/08/31/computer-algorithms-graphs-and-their-representation/" rel="bookmark" title="Computer Algorithms: Graphs and their Representation">Computer Algorithms: Graphs and their Representation </a></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<h2>Introduction</h2>
<p>The Strassen’s method of matrix multiplication is a typical divide and conquer algorithm. We’ve seen so far some divide and conquer algorithms like <a href="/2012/03/05/computer-algorithms-merge-sort/" title="Computer Algorithms: Merge Sort">merge sort</a> and the <a href="/2012/05/15/computer-algorithms-karatsuba-fast-multiplication/" title="Computer Algorithms: Karatsuba Fast Multiplication">Karatsuba’s fast multiplication</a> of large numbers. However let’s get again on what’s behind the divide and conquer approach.</p>
<p>Unlike the dynamic programming where we “expand” the solutions of sub-problems in order to get the final solution, here we are talking more on joining sub-solutions together. These solutions of some sub-problems of the general problem are equal and their merge is somehow well defined.</p>
<p>A typical example is the merge sort algorithm. In merge sort we have two sorted arrays and all we want is to get the array representing their union again sorted. Of course, the tricky part in merge sort is the merging itself. That’s because we’ve to pass through the two arrays, A and B, and we’ve to compare each “pair” of items representing an item from A and from B. A bit off topic, but this is the weak point of merge sort and although its worst-case time complexity is O(n.log(n)), quicksort is often preferred in practice because there’s no “merge”. <a href="/2012/03/13/computer-algorithms-quicksort/" title="Computer Algorithms: Quicksort">Quicksort</a> just concatenates the two sub-arrays. Note that in quicksort the sub-arrays aren’t with an equal length in general and although its worst-case time complexity is O(n^2) it often outperforms merge sort.</p>
<p>This simple example from the paragraph above shows us how sometimes merging the solutions of two sub-problems actually isn’t a trivial task to do. Thus we must be careful when applying any divide and conquer approach.</p>
<h2>History</h2>
<p><a href="http://en.wikipedia.org/wiki/Volker_Strassen" title="Volker Strassen" target="_blank">Volker Strassen</a> is a German mathematician born in 1936. He is well known for his works on probability, but in the computer science and algorithms he’s mostly recognized because of his algorithm for matrix multiplication that’s still one of the main methods that outperforms the general matrix multiplication algorithm.</p>
<p>Strassen firstly published this algorithm in 1969 and proved that the n^3 algorithm isn’t the optimal one. Actually the given solution by Strassen is slightly better, but his contribution is enormous because this resulted in many more researches about matrix multiplication that led to some faster approaches, i.e. <a href="http://en.wikipedia.org/wiki/Coppersmith%E2%80%93Winograd_algorithm" title="Coppersmith-Winograd algorithm" target="_blank">the Coppersmith-Winograd algorithm</a> with O(n^2,3737).<span id="more-3466"></span></p>
<h2>Overview</h2>
<p>The general algorithm on multiplying two matrices A[NxN] and B[NxN] is fairly simple. Although it’s more difficult than multiplying two numbers and also it is not commutative it’s still very simple – but slow.</p>
<p>Let’s first define what’s a matrix A[NxN]. As we speak about matrices NxN we usually think of a square grid with N rows and N columns. In each row and column A[i][j] we’ve a value. </p>
<figure id="attachment_3489" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/11/1.-Square-matrix.png"><img src="/wp-content/uploads/2012/11/1.-Square-matrix.png" alt="Square matrix" title="Square matrix" width="620" height="399" class="size-full wp-image-3489" srcset="/wp-content/uploads/2012/11/1.-Square-matrix.png 620w, /wp-content/uploads/2012/11/1.-Square-matrix-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">&nbsp;</figcaption></figure>
<p>Of course, as developers, we can think of a matrix as a two-dimensional array. </p>
<pre lang="PHP">
// PHP two-dimensional array
$a = array(
    0 => array($v1, $v2, $v3, $v4),
    1 => array($v5, $v6, $v7, $v8),
    2 => array($v9, $v10, $v11, $v12),
); 
</pre>
<p>Don’t forget that a NxN matrix is just a private case for a matrix. We can equally likely have any other size of a matrix NxM (N <> M). </p>
<p>However the size of a matrix is crucial in order to multiply it with another matrix. Why is that? </p>
<p>As I said above multiplying matrices isn’t the same as multiplying numbers. First of all this operation isn’t commutative.</p>
<figure id="attachment_3488" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/11/2.-Commutative-problem.png"><img src="/wp-content/uploads/2012/11/2.-Commutative-problem.png" alt="Commutative problem" title="Commutative problem" width="620" height="399" class="size-full wp-image-3488" srcset="/wp-content/uploads/2012/11/2.-Commutative-problem.png 620w, /wp-content/uploads/2012/11/2.-Commutative-problem-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">&nbsp;</figcaption></figure>
<p>And the second problem is the way you multiply two matrices A with B.</p>
<figure id="attachment_3487" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/11/3.-Matrix-Multiplication.png"><img src="/wp-content/uploads/2012/11/3.-Matrix-Multiplication.png" alt="Matrix Multiplication" title="Matrix Multiplication" width="620" height="399" class="size-full wp-image-3487" srcset="/wp-content/uploads/2012/11/3.-Matrix-Multiplication.png 620w, /wp-content/uploads/2012/11/3.-Matrix-Multiplication-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">&nbsp;</figcaption></figure>
<p>Just because this works with NxN matrices we can see the problem with multiplying rectangular matrices. Indeed, this wouldn’t be possible unless the second dimension of A isn’t exactly equal to the first dimension of B. </p>
<figure id="attachment_3486" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/11/4.-Rect-Matrix-Multiplication.png"><img src="/wp-content/uploads/2012/11/4.-Rect-Matrix-Multiplication.png" alt="Rectangular Matrix Multiplication" title="Rectangular Matrix Multiplication" width="620" height="399" class="size-full wp-image-3486" srcset="/wp-content/uploads/2012/11/4.-Rect-Matrix-Multiplication.png 620w, /wp-content/uploads/2012/11/4.-Rect-Matrix-Multiplication-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">&nbsp;</figcaption></figure>
<p>Hopefully we are now talking about square matrices with exactly the same dimensions.</p>
<p>OK, so now we know how to multiply two square matrices (with the same dimensions NxN) and now let’s evaluate the time complexity for the general purpose algorithm.</p>
<p>As we know A.B = C only when:</p>
<pre>
C[i][j] = sum(A[i][k] * B[k][j]) for k = 0 .. n
</pre>
<p>Thus we have n^3 operations. Let’s try to find out a divide and conquer approach.</p>
<p>Indeed this isn’t difficult in case of matrices because as we know we can divide in matrix in smaller sub-matrices.</p>
<figure id="attachment_3485" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/11/5.-Divide-and-Conquer.png"><img src="/wp-content/uploads/2012/11/5.-Divide-and-Conquer.png" alt="Divide and Conquer" title="Divide and Conquer" width="620" height="399" class="size-full wp-image-3485" srcset="/wp-content/uploads/2012/11/5.-Divide-and-Conquer.png 620w, /wp-content/uploads/2012/11/5.-Divide-and-Conquer-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">&nbsp;</figcaption></figure>
<p>Now what do we have?</p>
<figure id="attachment_3484" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/11/6.-Divide-and-Conquer-Result.png"><img src="/wp-content/uploads/2012/11/6.-Divide-and-Conquer-Result.png" alt="Divide and Conquer Result" title="Divide and Conquer Result" width="620" height="399" class="size-full wp-image-3484" srcset="/wp-content/uploads/2012/11/6.-Divide-and-Conquer-Result.png 620w, /wp-content/uploads/2012/11/6.-Divide-and-Conquer-Result-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">&nbsp;</figcaption></figure>
<p>Again &#8211; the same complexity – we have 8 products and 4 sums. Where’s the catch? </p>
<p>Of course in order to get faster solution we’ve to be looking as Strassen did in 1969. He defined P1, P2, P3, P4, P5, P6 and P7 as defined on the image below.</p>
<figure id="attachment_3483" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/11/7.-Strassens-Algorithm.png"><img src="/wp-content/uploads/2012/11/7.-Strassens-Algorithm.png" alt="Strassen&#039;s Algorithm" title="Strassen&#039;s Algorithm" width="620" height="399" class="size-full wp-image-3483" srcset="/wp-content/uploads/2012/11/7.-Strassens-Algorithm.png 620w, /wp-content/uploads/2012/11/7.-Strassens-Algorithm-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">&nbsp;</figcaption></figure>
<h2>Complexity</h2>
<p>As I mentioned above the Strassen’s algorithm is slightly faster than the general matrix multiplication algorithm. The general algorithm’s time complexity is O(n^3), while the Strassen’s algorithm is O(n^2.80).</p>
<p>You can see on the chart below how slightly faster is this even for large n.</p>
<figure id="attachment_3482" style="width: 600px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/11/Strassens-Complexity.png"><img src="/wp-content/uploads/2012/11/Strassens-Complexity.png" alt="Strassen&#039;s Complexity" title="Strassen&#039;s Complexity" width="600" height="371" class="size-full wp-image-3482" srcset="/wp-content/uploads/2012/11/Strassens-Complexity.png 600w, /wp-content/uploads/2012/11/Strassens-Complexity-300x185.png 300w" sizes="(max-width: 600px) 100vw, 600px" /></a><figcaption class="wp-caption-text">&nbsp;</figcaption></figure>
<h2>Application</h2>
<p>Although this algorithm seems to be more close to pure mathematics than to computer practically everywhere we use NxN arrays we can benefit from matrix multiplication.</p>
<p>In the other hand the algorithm of Strassen is not much faster than the general n^3 matrix multiplication algorithm. That’s very important because for small n (usually n < 45) the general algorithm is practically a better choice. However as you can see from the chart above for n > 100 the difference can be very big.</p>
<p>In the same time typically NxN arrays are used always when we talk about adjacency matrix of graphs |V| = n and some graph algorithms practically depend on matrix multiplication. </p>
<div class='yarpp-related-rss'>
<p>Related posts:<ol>
<li><a href="/2013/01/14/computer-algorithms-multiplication/" rel="bookmark" title="Computer Algorithms: Multiplication">Computer Algorithms: Multiplication </a></li>
<li><a href="/2012/05/15/computer-algorithms-karatsuba-fast-multiplication/" rel="bookmark" title="Computer Algorithms: Karatsuba Fast Multiplication">Computer Algorithms: Karatsuba Fast Multiplication </a></li>
<li><a href="/2012/10/22/computer-algorithms-bellman-ford-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Bellman-Ford Shortest Path in a Graph">Computer Algorithms: Bellman-Ford Shortest Path in a Graph </a></li>
<li><a href="/2012/08/31/computer-algorithms-graphs-and-their-representation/" rel="bookmark" title="Computer Algorithms: Graphs and their Representation">Computer Algorithms: Graphs and their Representation </a></li>
</ol></p>
</div>
]]></content:encoded>
			<wfw:commentRss>/2012/11/26/computer-algorithms-strassens-matrix-multiplication/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Computer Algorithms: Heap and Heapsort</title>
		<link>/2012/08/07/computer-algorithms-heap-and-heapsort-data-structure/</link>
		<comments>/2012/08/07/computer-algorithms-heap-and-heapsort-data-structure/#comments</comments>
		<pubDate>Tue, 07 Aug 2012 12:33:15 +0000</pubDate>
		<dc:creator><![CDATA[Stoimen]]></dc:creator>
				<category><![CDATA[algorithms]]></category>
		<category><![CDATA[data structures]]></category>
		<category><![CDATA[Binary heap]]></category>
		<category><![CDATA[Binary tree]]></category>
		<category><![CDATA[Computing]]></category>
		<category><![CDATA[Discrete mathematics]]></category>
		<category><![CDATA[Heap]]></category>
		<category><![CDATA[Heapsort]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[next]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Priority queue]]></category>
		<category><![CDATA[purpose algorithm]]></category>
		<category><![CDATA[Quicksort]]></category>
		<category><![CDATA[sorting algorithm]]></category>
		<category><![CDATA[Sorting algorithms]]></category>
		<category><![CDATA[Tree]]></category>

		<guid isPermaLink="false">/?p=3278</guid>
		<description><![CDATA[Introduction Heapsort is one of the general sorting algorithms that performs in O(n.log(n)) in the worst-case, just like merge sort and quicksort, but sorts in place &#8211; as quicksort. Although quicksort’s worst-case sorting time is O(n2) it’s often considered that it beats other sorting algorithms in practice. Thus in practice quicksort is “faster” than heapsort. &#8230; <a href="/2012/08/07/computer-algorithms-heap-and-heapsort-data-structure/" class="more-link">Continue reading <span class="screen-reader-text">Computer Algorithms: Heap and Heapsort</span> <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>

Related posts:<ol>
<li><a href="/2012/07/03/computer-algorithms-balancing-a-binary-search-tree/" rel="bookmark" title="Computer Algorithms: Balancing a Binary Search Tree">Computer Algorithms: Balancing a Binary Search Tree </a></li>
<li><a href="/2012/08/24/computer-algorithms-finding-the-lowest-common-ancestor/" rel="bookmark" title="Computer Algorithms: Finding the Lowest Common Ancestor">Computer Algorithms: Finding the Lowest Common Ancestor </a></li>
<li><a href="/2012/06/22/computer-algorithms-binary-search-tree-data-structure/" rel="bookmark" title="Computer Algorithms: Binary Search Tree">Computer Algorithms: Binary Search Tree </a></li>
<li><a href="/2012/02/20/computer-algorithms-bubble-sort/" rel="bookmark" title="Computer Algorithms: Bubble Sort">Computer Algorithms: Bubble Sort </a></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<h2>Introduction</h2>
<p>Heapsort is one of the general sorting algorithms that performs in O(n.log(n)) in the worst-case, just like <a href="/2012/03/05/computer-algorithms-merge-sort/" title="Merge sort explained">merge sort</a> and <a href="/2012/03/13/computer-algorithms-quicksort/" title="Quicksort explained">quicksort</a>, but sorts in place &#8211; as quicksort. Although quicksort’s worst-case sorting time is O(n<sup>2</sup>) it’s often considered that it beats other sorting algorithms in practice. Thus in practice quicksort is “faster” than heapsort. In the same time developers tend to consider heapsort as more difficult to implement than other n.log(n) sorting algorithms.</p>
<p>In the other hand heapsort uses a special data structure, called heap, in order to sort items in place and this data structure is quite useful in some specific cases. Thus to understand heapsort we first need to understand what is a heap.</p>
<p>So first let&#8217;s take a look at what is a heap.</p>
<h2>Overview</h2>
<p>A heap is a complete binary tree, where all the parents are greater than their children (max heap). If all the children are greater than their parents it is considered to call the heap a min-heap. But first what is a complete binary tree? Well, this is a binary tree, where all the levels are full, except the last one, where all the items are placed on the left (just like on the image below).</p>
<p><figure id="attachment_3295" style="width: 619px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/08/1.-Complete-Binary-Tree.png"><img src="/wp-content/uploads/2012/08/1.-Complete-Binary-Tree.png" alt="Complete Binary Tree" title="Complete Binary Tree" width="619" height="345" class="size-full wp-image-3295" srcset="/wp-content/uploads/2012/08/1.-Complete-Binary-Tree.png 619w, /wp-content/uploads/2012/08/1.-Complete-Binary-Tree-300x167.png 300w" sizes="(max-width: 619px) 100vw, 619px" /></a><figcaption class="wp-caption-text">A complete binary tree is a structure where all the levels are completely full, except the last level, where all the items are placed on the left!</figcaption></figure><span id="more-3278"></span></p>
<p>Combined with the fact that each node contains a greater key than its children, a heap may look like the tree on the following diagram.</p>
<figure id="attachment_3294" style="width: 621px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/08/2.-Heap.png"><img src="/wp-content/uploads/2012/08/2.-Heap.png" alt="Heap" title="Heap" width="621" height="359" class="size-full wp-image-3294" srcset="/wp-content/uploads/2012/08/2.-Heap.png 621w, /wp-content/uploads/2012/08/2.-Heap-300x173.png 300w" sizes="(max-width: 621px) 100vw, 621px" /></a><figcaption class="wp-caption-text">In a max-heap each node contains a greater value than its children. Respectively in a min-heap each node contains a smaller value than its parent!</figcaption></figure>
<p>The thing is that if we put indices next to each node of this tree, starting from the root (index 1) and continuing from left to right on each level, we’ll get the following tree.</p>
<figure id="attachment_3293" style="width: 618px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/08/3.-Heap-Indexes.png"><img src="/wp-content/uploads/2012/08/3.-Heap-Indexes.png" alt="Heap Indices" title="Heap Indices" width="618" height="360" class="size-full wp-image-3293" srcset="/wp-content/uploads/2012/08/3.-Heap-Indexes.png 618w, /wp-content/uploads/2012/08/3.-Heap-Indexes-300x174.png 300w" sizes="(max-width: 618px) 100vw, 618px" /></a><figcaption class="wp-caption-text">Putting indices right to each node reveals the secret of the heap. The i-th node has left child exactly with the index 2*i, and right child with index 2*i+1! This is a great opportunity to put this tree into an array!</figcaption></figure>
<p>Now if we take a closer look to the picture above we can see that the indices of a node and its children are closely related. Thus for a node of an index <em>i</em> we see that its left child has the index <em>2*i</em>, while its right child’s index is <em>2*i + 1</em>.</p>
<p><em>This particular order gives us the possibility to store each heap in an array.</em></p>
<figure id="attachment_3292" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/08/4.-Heap-as-an-Array.png"><img src="/wp-content/uploads/2012/08/4.-Heap-as-an-Array.png" alt="Heap as an Array" title="Heap as an Array" width="620" height="399" class="size-full wp-image-3292" srcset="/wp-content/uploads/2012/08/4.-Heap-as-an-Array.png 620w, /wp-content/uploads/2012/08/4.-Heap-as-an-Array-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">The heap tree can be easily represented as an array!</figcaption></figure>
<p>Since in a heap its greater element is in the root of the tree (for max-heap, respectively in a min-heap its smallest element is the root) we need to answer two questions. </p>
<ol>
<li>How to build a heap out of an ordinary array?</li>
<li>After extracting the root, which is the greatest (smallest) item, how can we rebuild the heap in order to keep it a heap again?</li>
</ol>
<p>First let’s try to answer the first question. How to build a heap? Well, let’s forget about the array for a while and let’s take a look on a ordinary binary tree with only three nodes.</p>
<figure id="attachment_3291" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/08/5.-Heapify.png"><img src="/wp-content/uploads/2012/08/5.-Heapify.png" alt="Heapify" title="Heapify" width="620" height="317" class="size-full wp-image-3291" srcset="/wp-content/uploads/2012/08/5.-Heapify.png 620w, /wp-content/uploads/2012/08/5.-Heapify-300x153.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">Fixing a node and its children in order to form a valid Heap is often called heapify!</figcaption></figure>
<p>We see that the three green nodes destroy the structure of our heap, because the root (1) is smaller than its children (4) and (5). Thus we need to fix this problem and what we’re going to do is to swap the root with its biggest child. </p>
<figure id="attachment_3290" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/08/6.-Heapify-Part-1.png"><img src="/wp-content/uploads/2012/08/6.-Heapify-Part-1.png" alt="Heapify Part 2" title="Heapify Part 2" width="620" height="399" class="size-full wp-image-3290" srcset="/wp-content/uploads/2012/08/6.-Heapify-Part-1.png 620w, /wp-content/uploads/2012/08/6.-Heapify-Part-1-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">We first need to know which is the greatest out of the three items, than in case it is not the root, swap its value with the root!</figcaption></figure>
<p>As you can see on the picture above the <em>i</em>-th item is first compared to its left child. The greater of these two items is compared to the right child. Note that we don’t swap them &#8211; we just compare them to get which one is greater. Once we find the greatest of these three values we swap them with the root in case it&#8217;s not the root value.</p>
<p>Although now these three elements form a heap, by swapping the root with one of its children may destroy the heap constructed out of this child. That is why we continue the same procedure with it.</p>
<p>This actually gives us the procedure to heapify the three nodes constructed out of the <em>i</em>-th item and its children. However to build a heap from an arbitrary array we should perform this operation starting from floor(len[A] / 2) down to the first item in the array.</p>
<figure id="attachment_3289" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/08/7.-Random-Array-to-Heap.png"><img src="/wp-content/uploads/2012/08/7.-Random-Array-to-Heap.png" alt="Random Array to Heap" title="Random Array to Heap" width="620" height="399" class="size-full wp-image-3289" srcset="/wp-content/uploads/2012/08/7.-Random-Array-to-Heap.png 620w, /wp-content/uploads/2012/08/7.-Random-Array-to-Heap-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">Building a random array into a heap isn&#8217;t that difficult since we know that half of the complete tree items lay in it&#8217;s lowest level! Thus we start from floor(len[A] / 2)!</figcaption></figure>
<p>Why? Well, a complete binary tree with a full last level contains n/2 + 1 nodes in it. They don’t have children, thus we don’t need to check them &#8211; they are &#8220;sorted&#8221;. Indeed if we start from an item on the right of floor(len[A] / 2) there won’t be items with indices <em>2*i</em> and <em>2*i + 1</em>.</p>
<h2>Code</h2>
<p>So far we know how to build the heap. Next thing is to swap the first and the last element of the array and rebuild the heap. Here’s the PHP code of how to do this.</p>
<pre lang="PHP">
$a = array(1, 6, 3, 8, 2, 5, 4);

function heapify(&$a, &$i, &$heap_size)
{
    $l = $i*2 + 1;
    $r = $i*2 + 2;
    
    if ($l < $heap_size &#038;&#038; $a[$i] < $a[$l]) {
        $largest = $l;
    } else {
        $largest = $i;
    }
    
    if ($r < $heap_size &#038;&#038; $a[$largest] < $a[$r]) {
        $largest = $r;
    }
    
    if ($largest != $i) {
        $t = $a[$i];
        $a[$i] = $a[$largest];
        $a[$largest] = $t;
        
        heapify($a, $largest, $heap_size);
    }
}

function build_heap(&#038;$a, &#038;$heap_size)
{
    $len = floor($heap_size / 2);
    for ($i = $len; $i > -1; $i--) {
        heapify($a, $i, $heap_size);
    }
}

function heapsort(&$a)
{
    $heap_size = count($a);
    build_heap($a, $heap_size);
    
    while ($heap_size--) {
        $t = $a[$heap_size];
        $a[$heap_size] = $a[0];
        $a[0] = $t;
        build_heap($a, $heap_size);
    }
}

// 1 2 3 4 5 6 8
heapsort($a);
</pre>
<h2>Complexity</h2>
<p>OK, the last question is &#8211; how do we know that this algorithm sorts in place in n.log(n) time? Let’s explore the algorithm one more time. The heapify worst-case is when we start from the root down to the lowest level of the tree. In these terms if the tree height is <strong>h</strong>, the time is O(h), but because the tree is balanced (complete) the time in terms of n is O(log(n)). </p>
<p>In the other hand to build a heap we walk from floor(len[A] / 2) to 0, which makes it run in O(n.log(n)). However there is only one case when the heapify may run in log(n), and that is when it starts from the root, so it’s not absolutely true that building the heap runs in n.log(n).</p>
<p>Indeed heapify depend on the level it has been started. It doesn’t run for the last ceil(n/2) items and it runs in O(1) for another 2<sup>h-1</sup>. Thus in practice we can build a heap in O(n). </p>
<p>Once we have the heap built, the only thing to do is to extract its first element and rebuild &#8211; heapify from the first item. This makes the sorting algorithm run in O(n.log(n)) &#8211; just like quicksort and mergesort.</p>
<h2>Application</h2>
<p>As I said in the beginning of this post quicksort is often the fastest general purpose algorithm in practice. This makes both merge sort and heapsort not so popular. However heapsort introduces an interesting data structure which can help us in many other cases. </p>
<p>It’s initially used to implement priority queues. What is great about a heap is that after we build it, which we know how to do in linear time, we can extract the greatest value &#8211; thus taking the highest priority task. Then with rebuilding the heap we can extract the next priority and so on, without fully sorting the array. </p>
<p>This makes the heapsort the only sorting algorithm that can sort the first <strong>k</strong> items out of a set of <strong>n</strong> items without sorting the whole set.</p>
<p>Indeed let’s say we have a set of positive integers and we’d like to get the biggest sum out of three items. Obviously we can sort the array and take the greatest three numbers, but this will cost us n.log(n) time, while using heapsort we can do it much faster! And all this without extra space &#8211; in place!</p>
<div class='yarpp-related-rss'>
<p>Related posts:<ol>
<li><a href="/2012/07/03/computer-algorithms-balancing-a-binary-search-tree/" rel="bookmark" title="Computer Algorithms: Balancing a Binary Search Tree">Computer Algorithms: Balancing a Binary Search Tree </a></li>
<li><a href="/2012/08/24/computer-algorithms-finding-the-lowest-common-ancestor/" rel="bookmark" title="Computer Algorithms: Finding the Lowest Common Ancestor">Computer Algorithms: Finding the Lowest Common Ancestor </a></li>
<li><a href="/2012/06/22/computer-algorithms-binary-search-tree-data-structure/" rel="bookmark" title="Computer Algorithms: Binary Search Tree">Computer Algorithms: Binary Search Tree </a></li>
<li><a href="/2012/02/20/computer-algorithms-bubble-sort/" rel="bookmark" title="Computer Algorithms: Bubble Sort">Computer Algorithms: Bubble Sort </a></li>
</ol></p>
</div>
]]></content:encoded>
			<wfw:commentRss>/2012/08/07/computer-algorithms-heap-and-heapsort-data-structure/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
