{"id":4356,"date":"2015-02-09T11:10:10","date_gmt":"2015-02-09T19:10:10","guid":{"rendered":"https:\/\/blog.digilentinc.com\/?p=4356"},"modified":"2025-01-30T15:11:09","modified_gmt":"2025-01-30T23:11:09","slug":"recursive-sorting-algorithms","status":"publish","type":"post","link":"https:\/\/digilent.com\/blog\/recursive-sorting-algorithms\/","title":{"rendered":"Recursive Sorting Algorithms"},"content":{"rendered":"<p>Welcome Back!<\/p>\n<p>&nbsp;<\/p>\n<p>Now that we know about <a href=\"https:\/\/digilent.com\/blog\/recursion\/\" target=\"_blank\" rel=\"noopener\">recursion<\/a>, we can talk about an important topic in programming\u00a0&#8212;\u00a0recursive sorting algorithms!<\/p>\n<p>&nbsp;<\/p>\n<p>If you check out the <a href=\"https:\/\/digilent.com\/blog\/what-are-pointers\/\" target=\"_blank\" rel=\"noopener\">pointers<\/a> blog post, we go over bubble sort, an iterative sorting algorithm. The problem with bubble sort is that it has an average time complexity of O(n^2), meaning that for every n items, it takes n^2 operations.<\/p>\n<p>&nbsp;<\/p>\n<p>Today, we&#8217;re going to go over quick-sort and merge-sort, both of which have an average time complexity of O(n*log(n)). What&#8217;s the difference between O(n^2) and O(n*log(n))? Let&#8217;s make a small chart to show the differences.<br \/>\n<a href=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/time.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4360\" src=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/time.png\" alt=\"time\" width=\"453\" height=\"172\" srcset=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/time.png 453w, https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/time-225x85.png 225w\" sizes=\"auto, (max-width: 453px) 100vw, 453px\" \/><\/a><\/p>\n<p>The time sections on the right assume that our computer can do one operation every one one-thousandth of a second (which is slow by modern standards, but still shows the differences well). When &#8220;n&#8221; is very large (say a million), the O(n^2) algorithms will take about 31 years to complete (or till 2046), while the 0(n*log(n)) will take about 100 minutes, which is pretty reasonable for sorting a million items.<\/p>\n<p>&nbsp;<\/p>\n<p>So why even bother with bubble-sort if there are sorting algorithms that are so much more efficient? Bubble-sort does have advantages, especially if space is an issue. But today we aren&#8217;t really going to worry about that.<br \/>\n<strong>Merge-Sort <\/strong><br \/>\n<a href=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/mergesort.gif\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4389\" src=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/mergesort.gif\" alt=\"mergesort\" width=\"300\" height=\"180\" \/><\/a><br \/>\n<a href=\"http:\/\/commons.wikimedia.org\/wiki\/File:Merge-sort-example-300px.gif\">Credit to the Wikimedia Commons<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<p>Mergesort is a divide-and-conquer algorithm that divides an array of length <em>n<\/em> into <em>n<\/em> subarrays, and then recombines them using merge. Our Mergesort has two main functions: <em>mergesort <\/em>and <em>merge<\/em>.<br \/>\n<a href=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/mergesort.txt\">mergesort<\/a><\/p>\n<p><a href=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/mergesort.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-4414\" src=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/mergesort.png\" alt=\"mergesort\" width=\"541\" height=\"461\" srcset=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/mergesort.png 541w, https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/mergesort-225x192.png 225w\" sizes=\"auto, (max-width: 541px) 100vw, 541px\" \/><\/a><br \/>\nMergesort is our recursive call, we take our array that has been passed into mergesort, then we <em>divide<\/em> the array into two halves and call mergesort recursively. This continues until each array has a size of 1. Then we return and merge (<em>conquer<\/em>). If we check out the code before we call mergesort again, you can see that there is the base case, and after that, the array list is being divided and moved into two smaller <a href=\"https:\/\/digilent.com\/blog\/what-are-arrays-again\/\" target=\"_blank\" rel=\"noopener\">arrays<\/a>.<\/p>\n<p><a href=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/mergef.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-4416\" src=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/mergef-471x600.png\" alt=\"mergef\" width=\"471\" height=\"600\" srcset=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/mergef-471x600.png 471w, https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/mergef-177x225.png 177w, https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/mergef.png 543w\" sizes=\"auto, (max-width: 471px) 100vw, 471px\" \/><\/a><br \/>\nMerge takes two arrays, and combines them. The two arrays have both been sorted by a previous call (except arrays with size 1, which can&#8217;t really be sorted). Then the arrays are sorted by checking the lowest value and moving them into a third array. The mergesort gif above is a really good way to show how merge sort works.<br \/>\n<a href=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/mergemain.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4420\" src=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/mergemain.png\" alt=\"mergemain\" width=\"560\" height=\"440\" srcset=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/mergemain.png 560w, https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/mergemain-225x177.png 225w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><br \/>\n<a href=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/mergesort.txt\">Mergesort Code<\/a><\/p>\n<p>Here we have a small main that calls mergesort!<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Quicksort<\/strong><br \/>\n<a href=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/quicksort.gif\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4331\" src=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/quicksort.gif\" alt=\"quicksort\" width=\"280\" height=\"214\" \/><\/a><br \/>\n<a href=\"http:\/\/en.wikipedia.org\/wiki\/Quicksort\">Credit to Wikipedia<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<p>Instead of dividing an array into N subdivisions like mergesort, quicksort uses partitions to divide the array into subarrays. The division of the subarrays is decided by the pivot point, which is decided by the algorithm (like the first or last variable in the array), then move all the values less than the pivot point to one side, and the higher values to the other side. Our quicksort implementation has four\u00a0functions in it: swap, partition, and two\u00a0quicksorts (one is just for ease of use).<\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/swap.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-4430\" src=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/swap-600x206.png\" alt=\"swap\" width=\"600\" height=\"206\" srcset=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/swap-600x206.png 600w, https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/swap-225x77.png 225w, https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/swap.png 630w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/a><br \/>\nSwap is a small function that switches to values of a list using the input parameters <em>left <\/em>and <em>right.<\/em><\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/partition.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4442\" src=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/partition.png\" alt=\"partition\" width=\"380\" height=\"467\" srcset=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/partition.png 380w, https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/partition-183x225.png 183w\" sizes=\"auto, (max-width: 380px) 100vw, 380px\" \/><\/a><\/p>\n<p>Partition is the &#8220;meat&#8221; of quicksort, and our implementation of quicksort takes the first value of low to use as the pivot point, and divides the array based of the point.<\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/quicksort.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4444\" src=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/quicksort.png\" alt=\"quicksort\" width=\"383\" height=\"291\" srcset=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/quicksort.png 383w, https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/quicksort-225x171.png 225w\" sizes=\"auto, (max-width: 383px) 100vw, 383px\" \/><\/a><br \/>\nOur quicksort functions are not too difficult, most of the work is done in partition. Here we call partition to divide list, and then call Quicksort recursively until we reach our base case. If you check out our main for Mergesort main, we call mergesort(B, N). We&#8217;ve changed this in quicksort by using function overloading, now in our main we can either call <em>quickSort(list, 0, N-1)<\/em>, which will start partitioning at 0 and N-1, or <em>quickSort(list)<\/em>, which then calls quickSort with the partition calls.<br \/>\n<a href=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/quickmain.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4448\" src=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/quickmain.png\" alt=\"quickmain\" width=\"560\" height=\"472\" srcset=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/quickmain.png 560w, https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/quickmain-225x190.png 225w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><br \/>\n<a href=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/quicksort.txt\">Quicksort Code<\/a><br \/>\nHere&#8217;s an example of us calling quicksort!<br \/>\n<a href=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/time2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-4449\" src=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/time2-600x278.png\" alt=\"time2\" width=\"600\" height=\"278\" srcset=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/time2-600x278.png 600w, https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/time2-225x104.png 225w, https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/time2.png 666w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/a><br \/>\n<a href=\"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/timer.txt\">Comparison code<\/a><br \/>\nHere is an efficiency comparison between quicksort and bubblesort. Using 50000 randomly generated values, we can time how long each function takes to sort the same array. The time is displayed in seconds, so you can try it out yourself!<\/p>\n<p>&nbsp;<\/p>\n<p><em>(Note: You can change N to more or less, and this will make change the amount of values to be sorted. 50000 was a good number to show the differences.)<\/em><\/p>\n<div class='watch-action'><div class='watch-position align-left'><div class='action-like'><a class='lbg-style6 like-4356 jlk' data-task='like' data-post_id='4356' data-nonce='ee750c7abc' rel='nofollow'><img src='https:\/\/digilent.com\/blog\/wp-content\/plugins\/wti-like-post-pro\/images\/pixel.gif' title='Like' \/><span class='lc-4356 lc'>+5<\/span><\/a><\/div><div class='action-unlike'><a class='unlbg-style6 unlike-4356 jlk' data-task='unlike' data-post_id='4356' data-nonce='ee750c7abc' rel='nofollow'><img src='https:\/\/digilent.com\/blog\/wp-content\/plugins\/wti-like-post-pro\/images\/pixel.gif' title='Unlike' \/><span class='unlc-4356 unlc'>-1<\/span><\/a><\/div><\/div> <div class='status-4356 status align-left'><\/div><\/div><div class='wti-clear'><\/div>","protected":false},"excerpt":{"rendered":"<p>Now that we know about recursion, we can talk about an important topic in programming &#8212; recursive sorting algorithms!<\/p>\n","protected":false},"author":29,"featured_media":4331,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1563],"tags":[],"ppma_author":[4478],"class_list":["post-4356","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-guide"],"jetpack_featured_media_url":"https:\/\/digilent.com\/blog\/wp-content\/uploads\/2015\/01\/quicksort.gif","authors":[{"term_id":4478,"user_id":29,"is_guest":0,"slug":"josh-woldstad","display_name":"Josh","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/b4b62729a3daba9bb76117db7130e81e?s=96&d=mm&r=g","author_category":"","user_url":"","last_name":"Woldstad","last_name_2":"","first_name":"Josh","first_name_2":"","job_title":"","description":"I love Coding!"}],"post_mailing_queue_ids":[],"_links":{"self":[{"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/posts\/4356","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/users\/29"}],"replies":[{"embeddable":true,"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/comments?post=4356"}],"version-history":[{"count":2,"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/posts\/4356\/revisions"}],"predecessor-version":[{"id":31321,"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/posts\/4356\/revisions\/31321"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/media\/4331"}],"wp:attachment":[{"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/media?parent=4356"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/categories?post=4356"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/tags?post=4356"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/digilent.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=4356"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}