<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: emuminov</title>
    <description>The latest articles on DEV Community by emuminov (@emuminov).</description>
    <link>https://dev.to/emuminov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2296206%2F9ba6fd65-fcda-44d0-8db4-7b56f0b8599d.jpeg</url>
      <title>DEV Community: emuminov</title>
      <link>https://dev.to/emuminov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/emuminov"/>
    <language>en</language>
    <item>
      <title>Ford-Johnson Algorithm: Human Explanation &amp; Visualisation</title>
      <dc:creator>emuminov</dc:creator>
      <pubDate>Wed, 13 Nov 2024 16:08:26 +0000</pubDate>
      <link>https://dev.to/emuminov/human-explanation-and-step-by-step-visualisation-of-the-ford-johnson-algorithm-5g91</link>
      <guid>https://dev.to/emuminov/human-explanation-and-step-by-step-visualisation-of-the-ford-johnson-algorithm-5g91</guid>
      <description>&lt;p&gt;Ford-Johnson sorting algorithm, or merge-insertion sort, is not a very well known or popular algorithm, which is optimised for making the least amount of comparisons between elements. The reason on why this algorithm is not well known is that it's neither fast, nor the best minimum sort algorithm, which is why there are almost no good resources on this algorithm, between scientific papers, hard to read computer science books, or obscure threads on Reddit or Stack Overflow.&lt;/p&gt;

&lt;p&gt;This algorithm has little to do with &lt;a href="https://en.wikipedia.org/wiki/Merge_sort" rel="noopener noreferrer"&gt;merge sort&lt;/a&gt; but is often confused with it. In the 42 school for cpp09 it's a common mistake, or sometimes a way to cheat, to implement much simpler hybrid sort between merge sort and binary insertion sort. This article aims to give an understanding of the algorithm using simple explanations and step-by-step execution of the algorithm on a set of 22 numbers.&lt;/p&gt;

&lt;p&gt;My name is Eldar, and I'm a student at 42 Lyon. Hence, the article will also have the context of one of the school assignments. I decided to write an article on this algorithm because almost no one does this algorithm correctly and understandably since it is hard, and easily one of the more complex sorting algorithms out there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps of the algorithm
&lt;/h2&gt;

&lt;p&gt;I recommend to read first &lt;a href="https://en.wikipedia.org/wiki/Merge-insertion_sort#Algorithm" rel="noopener noreferrer"&gt;Wikipedia's description of the algorithm&lt;/a&gt;, as well as &lt;a href="https://warwick.ac.uk/fac/sci/dcs/teaching/material-archive/cs341/fj.pdf" rel="noopener noreferrer"&gt;Knuth's&lt;/a&gt;. Both of those sources describe the steps of the algorithm a little bit differently. I intend to give my own explanation as well, as I believe that rewording helps to develop understanding; I will also later explain each step individually in depth. Hence, my explanation of the steps for sorting numbers using this algorithm in ascending order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Recursively divide into pairs of numbers, pairs of pairs of numbers, pairs of pairs of pairs of numbers... etc, and sort them by the biggest number, until we can't form any pair anymore. If there is an unpaired odd element, leave it be.

&lt;ul&gt;
&lt;li&gt;I will also refer to the units on which we operate on as &lt;code&gt;elements&lt;/code&gt;. &lt;code&gt;elements&lt;/code&gt; can be numbers, pairs of numbers, pairs of pairs of numbers etc...&lt;/li&gt;
&lt;li&gt;We will refer to the smallest element in each pair as &lt;code&gt;b&lt;/code&gt;, and to the biggest as &lt;code&gt;a&lt;/code&gt;. Depending on the index of the pair, we will call them &lt;code&gt;b1&lt;/code&gt;, &lt;code&gt;a1&lt;/code&gt;, &lt;code&gt;b2&lt;/code&gt;, &lt;code&gt;a2&lt;/code&gt;... &lt;code&gt;bx&lt;/code&gt;, &lt;code&gt;ax&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Create a sequence (also referred to as &lt;code&gt;S&lt;/code&gt; or &lt;code&gt;the main chain&lt;/code&gt; in Wikipedia and Knuth's book respectively) out of the smallest element of the smallest pair (&lt;code&gt;b1&lt;/code&gt;) and the rest of &lt;code&gt;a&lt;/code&gt;s. If the first step was done correctly, this sequence will be sorted. Create the sequence that consists of the rest of &lt;code&gt;b&lt;/code&gt;s (also referred to as &lt;code&gt;the pend&lt;/code&gt;), and the odd element if there is any.

&lt;ul&gt;
&lt;li&gt;I will refer to those sequences as &lt;code&gt;the main&lt;/code&gt; and &lt;code&gt;the pend&lt;/code&gt; from now on.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Binary insert the elements from the pend into the main, in the order based on &lt;a href="https://en.wikipedia.org/wiki/Jacobsthal_number" rel="noopener noreferrer"&gt;Jacobsthal numbers&lt;/a&gt;. I will explain later why and how it works. If we can't insert elements into &lt;code&gt;the main&lt;/code&gt; using Jacobsthal numbers anymore, we insert them in reverse order, using similar approach to the plain good ol' binary insertion.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Due to the fact that step 1 is recursive, it will create a bunch of recursion levels, to each of which steps 2 and 3 will be applied. It will look as something like this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F40v45mp53krg4j9fsjxy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F40v45mp53krg4j9fsjxy.png" alt="Steps of the algorithm" width="800" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If everything is done correctly, the sequence will be sorted. Of course, I omitted some of the details, for the sake of giving the general description on what we will be doing. The algorithm isn't easy to understand, and you aren't expected to understand it from the first read. After you'll see the visualisation of the algorithm using the established nomenclature, you will have a much better idea.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1: the division into the pairs &amp;amp; sorting
&lt;/h3&gt;

&lt;p&gt;This step is pretty confusing to understand, and also tricky to implement in code, but good visualisation helps. The difficulty is that with each recursion call we operate on bigger and bigger groups of elements: pairs of numbers on the first call, pairs of pairs of numbers on the second call, pairs of pairs of pairs of numbers on the third etc, until we can no longer divide our original sequence into a single pair of elements.&lt;/p&gt;

&lt;p&gt;On top of this, we also need to preserve the original pairing: we can't break pairs formed on the first recursion call on the fifth one. This is important for this algorithm, as it relies on certain guarantees about the elements: that the biggest element of &lt;code&gt;b2&lt;/code&gt; is smaller than the biggest element of &lt;code&gt;a2&lt;/code&gt;, &lt;code&gt;b3&lt;/code&gt; is smaller than &lt;code&gt;a3&lt;/code&gt;, &lt;code&gt;b4&lt;/code&gt; is smaller than &lt;code&gt;a4&lt;/code&gt;, &lt;code&gt;bx&lt;/code&gt; is smaller than &lt;code&gt;ax&lt;/code&gt;. This is important for the algorithm's nature of a minimum comparison sort. The easiest way to achieve this is to simply swap entire groupes of numbers with each other when we sort them. It'll be much clearer in a minute.&lt;/p&gt;

&lt;p&gt;For the visualisation I'll denote at the top, the recursion depth we are currently it. Because the algorithm requires recursive sorting of pairs before the insertion part, I can demonstrate this process in this section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F35gj9okahi19m0cflks7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F35gj9okahi19m0cflks7.png" alt="First step of pair sorting" width="800" height="643"&gt;&lt;/a&gt;&lt;br&gt;
This level of recursion depth is easy to wrap head around: here we operate just on numbers. If the number in the pair is bigger than the other one, we simply swap them in place. After sorting the pairs, I put the &lt;code&gt;b&lt;/code&gt; and &lt;code&gt;a&lt;/code&gt; labels that I described earlier underneath each element in the new sequence: now it should be clear how the labels work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ijwjza0q831vvzgr9q4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ijwjza0q831vvzgr9q4.png" alt="Second step of pair sorting" width="800" height="487"&gt;&lt;/a&gt;&lt;br&gt;
This is where it starts to get funky: now our element is a pair of numbers instead of just a number. Also, we have an odd element that is left without its pair. We name it &lt;code&gt;b6&lt;/code&gt;.&lt;br&gt;
On top of the white borders denoting pairs, here there are red borders for the pairs of pairs. Notice also that I placed the labels against the last number of each element: this is no coincedence, the labels reside under the number that we actually use for comparison/pair sorting: &lt;code&gt;11&lt;/code&gt; against &lt;code&gt;17&lt;/code&gt;, &lt;code&gt;16&lt;/code&gt; against &lt;code&gt;15&lt;/code&gt; etc, but the swapping happens on an entire subsequence of numbers. Green dotted border denotes an odd pair. Here, only one swap occures: of &lt;code&gt;8 16&lt;/code&gt; and of &lt;code&gt;6 15&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F437huv0m7yacyjqculp7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F437huv0m7yacyjqculp7.png" alt="Third step of pair sorting" width="800" height="509"&gt;&lt;/a&gt;&lt;br&gt;
Now we have a blue border to denote pairs of pairs of pairs... It's already mouthful to say. But we must go deeper.&lt;br&gt;
Notice that there are numbers without any borders: I chose this way to separate numbers who can't even form an element. At this level, the smallest unit on which we operate consists out of 4 numbers, and the pairs are formed out of 8 numbers. What we are gonna do with those numbers? Simple: we ignore them.&lt;br&gt;
At this level, two swaps occured: &lt;code&gt;2 11 0 17&lt;/code&gt; and &lt;code&gt;6 15 8 16&lt;/code&gt;, &lt;code&gt;3 10 1 21&lt;/code&gt; and &lt;code&gt;9 18 14 19&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feekme1aiue8sq83uayjv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feekme1aiue8sq83uayjv.png" alt="Fourth step of pair sorting" width="800" height="521"&gt;&lt;/a&gt;&lt;br&gt;
Now we are at the level of pairs of pairs of pairs of pairs. We have 22 elements, but the element here is formed out of 8 numbers: hence only one pair of two elements.&lt;br&gt;
&lt;code&gt;17&lt;/code&gt; is lesser than &lt;code&gt;21&lt;/code&gt;. Lucky us! No swaps happened at this level.&lt;/p&gt;

&lt;p&gt;There is nothing to be done at the level 5 of recursion: because the amount of numbers in the element doubles with each recursion call, at one point we won't be able to form a pair of elements. This is where we break from this level. Because at level 5 one element consists of 16 numbers, and we have only 22 numbers overall, pair of 2 elements is impossible to form. From now on, we proceed with the steps starting with the level 4, then we go to level 3, 2, 1... until we got our sorted number sequence.&lt;/p&gt;

&lt;p&gt;To really understand what's going on at the sorting of pairs level, I invite you to come up with a random sequence of numbers and try to sort them on paper. After doing it a couple of times, you will probably have some ideas on how to implement this step in code.&lt;/p&gt;
&lt;h3&gt;
  
  
  Steps 2 and 3: the initialization and insertion
&lt;/h3&gt;

&lt;p&gt;We will talk about those two steps together, as due to the recursive nature of the algorithm, they will alternate between each other. Step 1 operated on its own and created a 4 recursion levels, which are for steps 2 and 3 to resolve. Those steps are applied to each of the levels.&lt;/p&gt;

&lt;p&gt;Here is where the labels we defined earlier will come in handy.&lt;br&gt;
This step is pretty easy:&lt;br&gt;
&lt;code&gt;The main&lt;/code&gt; is initialised with the elements &lt;code&gt;{b1, a1}&lt;/code&gt; and then with the rest of &lt;code&gt;a&lt;/code&gt;s.&lt;br&gt;
&lt;code&gt;The pend&lt;/code&gt; is initialised with the rest of &lt;code&gt;b&lt;/code&gt;s starting from &lt;code&gt;b2&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;The main&lt;/code&gt; at this point should be sorted, but not entirely. Like with comparing and swapping at the step 1, only the biggest number in each element counts for "being sorted". Let's demonstrate this with the example we already have. This is where we're at after continuing on the level 4 of recursion:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl5e703l8ickbj7y05x1b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl5e703l8ickbj7y05x1b.png" alt="Recursion level 4 pend-main initialisation" width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not a lot of things to talk about at this recursion level: the pend is empty, as there are only two elements which go directly to &lt;code&gt;the main&lt;/code&gt;, since &lt;code&gt;b1&lt;/code&gt; and &lt;code&gt;a1&lt;/code&gt; both start as part of &lt;code&gt;the main&lt;/code&gt;. The reason for this is that we already know that &lt;code&gt;b1&lt;/code&gt; is smaller than &lt;code&gt;a1&lt;/code&gt;, and because of the logic of the algorithm, and what you will see from further visualisations, &lt;code&gt;the main&lt;/code&gt; is sorted, so &lt;code&gt;a1&lt;/code&gt; is smaller than any of the other &lt;code&gt;a&lt;/code&gt;s, hence no additional comparisons are needed. What counts as "sorted" are the biggest numbers in each element: in this case, in &lt;code&gt;b1&lt;/code&gt; and &lt;code&gt;a1&lt;/code&gt; those are &lt;code&gt;17&lt;/code&gt; and &lt;code&gt;21&lt;/code&gt; respectively. That is one of the optimisations of this algorithm to minimize comparisons.&lt;/p&gt;

&lt;p&gt;The numbers in the dotted red border &lt;code&gt;5 12 4 20 7 13&lt;/code&gt; are numbers which can't form even a single element. Just like in the step 1, they are still part of the sequence, they just don't participate in the insertion.&lt;/p&gt;

&lt;p&gt;One important thing to understand is that on that step, when we initialise &lt;code&gt;the pend&lt;/code&gt; and &lt;code&gt;the main&lt;/code&gt; the labels change. Elements can and will change their positions compared to their step 1 position because of all the swapping and insertion. On this step, you can think about it as if the labels refer the position of the elements: for example, on this level element consists of 8 numbers, so &lt;code&gt;b1&lt;/code&gt; will always consist of numbers at positions of 0-7, while &lt;code&gt;a1&lt;/code&gt; of numbers at positions of 8-15, &lt;code&gt;b2&lt;/code&gt;, and so on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frldt6a4q0r7wbb5jk74y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frldt6a4q0r7wbb5jk74y.png" alt="End of insertion of recursion 4" width="800" height="296"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nothing to say about step 3 at this recursion level, as there are no elements in &lt;code&gt;the pend&lt;/code&gt; at all. No &lt;code&gt;pend&lt;/code&gt; - no insertions. Move on. I will discuss insertion logic when we'll have something to insert.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm975srhu2d1t16ozr4bd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm975srhu2d1t16ozr4bd.png" alt="Recursion level 4 result" width="800" height="265"&gt;&lt;/a&gt;&lt;br&gt;
We are done with level 4: nothing else to do here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fko02rmgd5v6va2dgcsmu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fko02rmgd5v6va2dgcsmu.png" alt="Recursion level 3 pend-main initialisation" width="800" height="424"&gt;&lt;/a&gt;&lt;br&gt;
At this level our element consists of 4 numbers. From the start, we divide elements into &lt;code&gt;b&lt;/code&gt;s and &lt;code&gt;a&lt;/code&gt;s. We initialize &lt;code&gt;the pend&lt;/code&gt; and &lt;code&gt;the main&lt;/code&gt; as I said before: &lt;code&gt;the main&lt;/code&gt; is &lt;code&gt;b1&lt;/code&gt; and the rest of &lt;code&gt;a&lt;/code&gt;s, &lt;code&gt;the pend&lt;/code&gt; is the rest of &lt;code&gt;b&lt;/code&gt;s. Notice that &lt;code&gt;b&lt;/code&gt;s and &lt;code&gt;a&lt;/code&gt;s are changed. Remember what I told you about relabeling? We change the labels at the step 2 of each recursion level. Notice, however, that the actual number pairings remained unbroken.&lt;/p&gt;

&lt;p&gt;This time we have two elements in &lt;code&gt;the pend&lt;/code&gt;: &lt;code&gt;b2&lt;/code&gt; + the odd element that didn't participate in step 1, but is a full participant here. There is something to insert, so we can discuss how step 3 works.&lt;/p&gt;

&lt;p&gt;Step 3 can be pretty confusing. This is where binary insertion of our merge-&lt;strong&gt;insertion&lt;/strong&gt; algorithm comes in. What do I mean by binary insertion? It means that we use &lt;a href="https://en.wikipedia.org/wiki/Binary_search" rel="noopener noreferrer"&gt;binary search algorithm&lt;/a&gt; on our &lt;code&gt;main&lt;/code&gt;, which is a sorted sequence, to find a place for insertion for our &lt;code&gt;pend&lt;/code&gt; elements. Insertion itself works very similarly to how it's done in the &lt;a href="https://www.geeksforgeeks.org/binary-insertion-sort/" rel="noopener noreferrer"&gt;binary insertion sort&lt;/a&gt;, but with a twist: the insertion order from &lt;code&gt;the pend&lt;/code&gt; is dictated by mathematical sequence called Jacobsthal numbers.&lt;/p&gt;

&lt;p&gt;Before we proceed further, let's spend a little bit of time to understand what's going on here. Why Jacobsthal numbers? Why bother with them, what do they do with sorting?&lt;/p&gt;
&lt;h3&gt;
  
  
  Why Jacobsthal numbers?
&lt;/h3&gt;

&lt;p&gt;Ford-Johnson algorithm uses an important binary search algorithm optimisation that further cuts the number of times we compare our elements to each other. The maximal number of comparisons for the binary search is the same for &lt;code&gt;2^k&lt;/code&gt; as for &lt;code&gt;2^(k+1)-1&lt;/code&gt;. That means that the maximal number of comparisons is the same for 4(&lt;code&gt;2^2&lt;/code&gt;) and 7(&lt;code&gt;2^3-1&lt;/code&gt;). Same thing for 8 and 15, for 16 and 31... etc. This algorithm uses this property of the binary search during the insertion phase, if it can. What do I mean by "if it can"? Well, as you remember, we didn't used any Jacobsthal numbers during unrolling of our level 4 and 3 recursions. Wait, but how are those damn numbers related to this optimization? Well, turns out, that if you insert &lt;code&gt;the pend&lt;/code&gt; elements into &lt;code&gt;the main&lt;/code&gt; using a specific order dictated by the Jacobsthal numbers and we respect the bound elements, the surface area for insertions is &lt;code&gt;2^(k+1)-1&lt;/code&gt; for (nearly) all elements, as opposed to &lt;code&gt;2^k&lt;/code&gt; for the first element and God knows what for next elements, since we would naively insert numbers as in regular binary insertion (like we did during the insertion at the recursion level 3).&lt;/p&gt;

&lt;p&gt;The way Jacobsthal numbers dictate the order of insertion is like this: we start from the Jacobsthal number of 3. We start insertion from element &lt;code&gt;b3&lt;/code&gt;. We insert elements in the reverse order starting from this element, until we hit &lt;code&gt;b&lt;/code&gt; element of number of previous Jacobsthal number. In other words, the amount of inserted elements is &lt;code&gt;current_jacobsthal - previous_jacobsthal&lt;/code&gt;.&lt;br&gt;
For the Jacobsthal number of 3, we insert 2 elements (3 - 1), &lt;code&gt;b3, b2&lt;/code&gt;.&lt;br&gt;
For the Jacobsthal number of 5, we insert 2 elements (5 - 3), &lt;code&gt;b5, b4&lt;/code&gt;.&lt;br&gt;
For the Jacobsthal number of 11, we insert 6 elements (11 - 5), &lt;code&gt;b11, b10, b9, b8, b7, b6&lt;/code&gt;.&lt;br&gt;
I hope that you got the idea. And that you understand now that we can't always insert numbers this way. If there's not enough elemets to insert, for example, the Jacobsthal number is 11 (we should insert 6 elements), but we have only 3 elements in &lt;code&gt;the pend&lt;/code&gt;, then we need to handle it somehow, and the simplest way to do this is to insert &lt;code&gt;the pend&lt;/code&gt; elements in order, as we did in recursion level 3.&lt;/p&gt;

&lt;p&gt;Ok, but now again, how exactly this order optimises the amount of comparisons for our binary insertion? Let's look at what happens if we insert pend elements in this specific order! Time for another visual example! Yay!&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F06fk1jice91layp3yud7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F06fk1jice91layp3yud7.png" alt="Jacobsthal numbers insertion example" width="800" height="696"&gt;&lt;/a&gt;&lt;br&gt;
The elements are ordered by labels in these exapmples, but the actual order with actual numbers might be more mixed, so it's like this in the example for clarity.&lt;br&gt;
As you can see, the order dictated by the Jacobsthal numbers is what allows us to use this optimisation in the algorithm: we can insert large amount pend elements into the main with binary search only on &lt;code&gt;2^(k+1)-1&lt;/code&gt; elements. This works because due to how the algorithm works, we know that the bound for &lt;code&gt;bx&lt;/code&gt; is &lt;code&gt;ax&lt;/code&gt;. So when we insert, for example &lt;code&gt;b5&lt;/code&gt; instead of searching in &lt;code&gt;{b1, a1, b2, a2, b3, a3, a4, a5, a6, a7, ...}&lt;/code&gt; we can search in &lt;code&gt;{b1, a1, b2, a2, b3, a3, a4}&lt;/code&gt;, because we know that there is no point to include into the search range &lt;code&gt;a5&lt;/code&gt; and anything after that since they are guarenteed to be bigger. After we inserted &lt;code&gt;b5&lt;/code&gt; and it is time to insert &lt;code&gt;b4&lt;/code&gt;, the bound is decreased by one (from &lt;code&gt;a5&lt;/code&gt; to &lt;code&gt;a4&lt;/code&gt;), but the amount of elements is increased by one (we inserted &lt;code&gt;b5&lt;/code&gt;), so the amount of elements in this range stayed the same. &lt;br&gt;
Note: &lt;em&gt;however&lt;/em&gt;, sometimes, as we will see soon, the Jacobsthal number insertions guarantee &lt;code&gt;2^(k+1)-1&lt;/code&gt; in the &lt;em&gt;worst&lt;/em&gt; case. In the best case the range of search may be even smaller, if inserted element is going to be bigger than any other number in the search range. Then, for the next number the search range will actually be lower. You will see this in the continuation of the execution.&lt;/p&gt;

&lt;p&gt;Now that we understood what purpose the Jacobsthal numbers have here, I want to bring up that there is also an optimal way to calculate the n'th Jacobsthal number. Rounded result of &lt;code&gt;(2^(n+1) + (-1)^n) / 3&lt;/code&gt; will produce an offsetted for our use case (it normally starts from 0) Jacobsthal number.&lt;/p&gt;
&lt;h3&gt;
  
  
  Back to where we left
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbhy5fdfkruapuq6jlj6e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbhy5fdfkruapuq6jlj6e.png" alt="Recursion level 3 insertion 1" width="800" height="289"&gt;&lt;/a&gt;&lt;br&gt;
I will mark the current element for insertion from &lt;code&gt;the pend&lt;/code&gt; with the blue border. The range of elements that we will try to insert this element into with the green border, and the "bound" element, ie corresponding &lt;code&gt;a&lt;/code&gt; element, with the red border. "Bound" marks the end of the area of search.&lt;/p&gt;

&lt;p&gt;The current Jacobsthal number is 3, which means that we start with &lt;code&gt;b3&lt;/code&gt; from &lt;code&gt;the pend&lt;/code&gt;. The bound element for &lt;code&gt;b3&lt;/code&gt; is &lt;code&gt;a3&lt;/code&gt;, and we should try to insert it into &lt;code&gt;{b1, a1, a2}&lt;/code&gt;. Since there is no &lt;code&gt;a3&lt;/code&gt; element, because &lt;code&gt;b3&lt;/code&gt; is an odd numer, we compare it with the entire &lt;code&gt;main&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In other words, we should compare &lt;code&gt;20&lt;/code&gt;, the biggest number in the element, to &lt;code&gt;{16, 17, 21}&lt;/code&gt;, the biggest numbers in the elements of our search area, and then insert the whole element after that in it's corresponding place.&lt;/p&gt;

&lt;p&gt;Since &lt;code&gt;20&lt;/code&gt; is bigger than &lt;code&gt;16&lt;/code&gt; or &lt;code&gt;17&lt;/code&gt;, we insert the entire element &lt;code&gt;b2&lt;/code&gt; (&lt;code&gt;5 12 4 20&lt;/code&gt;) between &lt;code&gt;a1&lt;/code&gt; (&lt;code&gt;2 11 0 17&lt;/code&gt;) and &lt;code&gt;a2&lt;/code&gt; (&lt;code&gt;3 10 1 21&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7goq01lhok0rrc1gk58p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7goq01lhok0rrc1gk58p.png" alt="Recursion level 3 insertion 2" width="800" height="289"&gt;&lt;/a&gt;&lt;br&gt;
The Jacobsthal number is still 3, and the next element for insertion is &lt;code&gt;b2&lt;/code&gt;. Its bound element is &lt;code&gt;a2&lt;/code&gt;: we already know that it's smaller that this element, so we try to insert it into &lt;code&gt;{b1, a1, b3}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7v2emjvvxnwqwks8h39q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7v2emjvvxnwqwks8h39q.png" alt="Recursion level 3 end of insertion" width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwzoqijblqmp6zrzylxmh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwzoqijblqmp6zrzylxmh.png" alt="Recursion 3 result" width="800" height="263"&gt;&lt;/a&gt;&lt;br&gt;
So, at the moment, our sequence is this: &lt;code&gt;6 15 8 16 2 11 0 17 9 18 14 19 5 12 4 20 3 10 1 21 7 13&lt;/code&gt;. When we go down a recursion level, &lt;code&gt;the main&lt;/code&gt; and &lt;code&gt;the pend&lt;/code&gt; initialisation, as well as insertion, will go from this sequence.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffut2jeujnwdftqcn3w6n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffut2jeujnwdftqcn3w6n.png" alt="Recursion level 2 pend-main initialisation" width="800" height="424"&gt;&lt;/a&gt;&lt;br&gt;
We divide the resulting sequence into the elements again, and initialize our &lt;code&gt;main&lt;/code&gt; and &lt;code&gt;pend&lt;/code&gt;. The sequence has changed since the recursion level of 3, and the labels too: but the original pairs (like &lt;code&gt;((2 11) (0 17))&lt;/code&gt;) remained unbroken. So the guarantee that the &lt;code&gt;(2, 11)&lt;/code&gt; (now &lt;code&gt;b2&lt;/code&gt;) element is smaller than &lt;code&gt;(0, 17)&lt;/code&gt; (now &lt;code&gt;a2&lt;/code&gt;) is still valid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwhs8nhgv8pgor7wgyxq9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwhs8nhgv8pgor7wgyxq9.png" alt="Recursion level 2 insertion 1" width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqcb9jssxdsojr3ngjhme.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqcb9jssxdsojr3ngjhme.png" alt="Recursion level 2 insertion 2" width="800" height="290"&gt;&lt;/a&gt;&lt;br&gt;
So, we inserted our &lt;code&gt;b3&lt;/code&gt; into &lt;code&gt;the main&lt;/code&gt;, but as you can see, it shrinks the search area for the &lt;code&gt;b2&lt;/code&gt;, as this element turned out bigger than &lt;code&gt;a2&lt;/code&gt;, so the area of search shrank. Remember the note from the "Why Jacobsthal numbers?" part? This is the example. It may happen sometimes, and it's another tricky thing of this algorithm that needs to be accounted for.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpy1uq0enfarjw8ze8rg1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpy1uq0enfarjw8ze8rg1.png" alt="Recursion level 2 insertion 3" width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F538vtjqb3q0nw6rk5kha.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F538vtjqb3q0nw6rk5kha.png" alt="Recursion level 2 insertion 4" width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4e9fkk6e1ix769bez4z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4e9fkk6e1ix769bez4z.png" alt="Recursion level 2 insertion 5" width="800" height="290"&gt;&lt;/a&gt;&lt;br&gt;
Oops! We run out of the Jacobsthal numbers. There is only one element left in &lt;code&gt;the pend&lt;/code&gt;! What to do? We do almost the same thing as we do on the binary search: we insert &lt;code&gt;the pend&lt;/code&gt; elements, but in the &lt;strong&gt;reverse order&lt;/strong&gt;, meaning that we start from the end. We do it like that in order to keep the search area the same. Of course, you still have to respect the bound element: for example, if we insert &lt;code&gt;b3&lt;/code&gt; in this way, the area of search still doesn't include &lt;code&gt;a3&lt;/code&gt; and further. In this case, it's an odd element, so there is no corresponding bound element.&lt;/p&gt;

&lt;p&gt;Ok, so now, I think, we are fully equipped to comprehend the rest of the algorithm, so let's proceed with its steps without any more yapping!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5x9iwtq4eaz9xfvxk70v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5x9iwtq4eaz9xfvxk70v.png" alt="Recursion level 2 end of insertion" width="800" height="291"&gt;&lt;/a&gt;&lt;br&gt;
With this, the second level of the recursion was resolved. The resulting sequence after this level looks like this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fay6y016qn781zokyoatj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fay6y016qn781zokyoatj.png" alt="Recursion 2 result" width="800" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2gvx3k2f8bnylqpr4y2a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2gvx3k2f8bnylqpr4y2a.png" alt="Recursion level 1 pend-main initialisation" width="800" height="424"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flbv772aix9djnjb8kknt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flbv772aix9djnjb8kknt.png" alt="Recursion level 1 insertion 1" width="800" height="291"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3u68fmj7d77fb8yismid.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3u68fmj7d77fb8yismid.png" alt="Recursion level 1 insertion 2" width="800" height="291"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi68v2196abv8m8wbw53i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi68v2196abv8m8wbw53i.png" alt="Recursion level 1 insertion 3" width="800" height="291"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9fh1118iymv1fzfujkkq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9fh1118iymv1fzfujkkq.png" alt="Recursion level 1 insertion 4" width="800" height="291"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0sf0i4wgc8icn7rb76r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0sf0i4wgc8icn7rb76r.png" alt="Recursion level 1 insertion 5" width="800" height="291"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo3enoxtlee2tnjci0ftk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo3enoxtlee2tnjci0ftk.png" alt="Recursion level 1 insertion 6" width="800" height="291"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgr4qgv0uakk4adakzphp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgr4qgv0uakk4adakzphp.png" alt="Recursion level 1 insertion 7" width="800" height="291"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm975erm41a7et7g73z50.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm975erm41a7et7g73z50.png" alt="Recursion level 1 insertion 8" width="800" height="291"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm5l74p2yz2uvzfurn2x3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm5l74p2yz2uvzfurn2x3.png" alt="Recursion level 1 insertion 9" width="800" height="291"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4z1gmi08u92ehg95x972.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4z1gmi08u92ehg95x972.png" alt="Recursion level 1 insertion 10" width="800" height="291"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv300rr9vkgkmoadq31mb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv300rr9vkgkmoadq31mb.png" alt="Recursion level 1 end of insertion" width="800" height="291"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8a8qzuk2yugodn70x4hy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8a8qzuk2yugodn70x4hy.png" alt="Final result" width="800" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And with this, our sequence became sorted. This algorithm is not an easy one to understand and also to implement, but both swapping and insertion follow specific patterns, peculiarities of which you can calculate, if you do this algorithm on paper/in your favorite text editor again and again, which I encourage you to do, as doing is the only way to really cement theory.&lt;/p&gt;
&lt;h2&gt;
  
  
  Testing the algorithm implementation
&lt;/h2&gt;

&lt;p&gt;This is a minimal comparisons sort, so your algorithm should perform no more than &lt;code&gt;k&lt;/code&gt; comparisons for the input of &lt;code&gt;n&lt;/code&gt; numbers. For example, for 21 numbers the maximal number of comparisons is 66, so if you run this algorithm 1000 times on 21 random numbers, it will never exceed 66 comparisons.&lt;/p&gt;

&lt;p&gt;There is a mathematical way to calculate &lt;code&gt;k&lt;/code&gt; given the &lt;code&gt;n&lt;/code&gt;. The formula was described by Knuth in his book, which in turn was discovered by A. Hadian in 1969.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkyoa0k3zxuxctusegdlk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkyoa0k3zxuxctusegdlk.png" alt="Max comparisons formula" width="742" height="208"&gt;&lt;/a&gt;&lt;br&gt;
For people who aren't on friendly terms with math: this formula is actually very simple to implement in code. Math people just like terse scary symbols.&lt;br&gt;
Using C++, &lt;code&gt;F(n)&lt;/code&gt; can be written as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;F&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="k"&gt;static_cast&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next step after that is to implement in your code a comparison function, which goal is simply to increment some global/static variable each time its called. You use it every time you need to perform a comparison between numbers, including passing it to &lt;code&gt;std::upper_bound&lt;/code&gt; or a similar function, if you are going to use that.&lt;/p&gt;

&lt;p&gt;Run functions a lot of times for a given &lt;code&gt;n&lt;/code&gt;, using different &lt;code&gt;n&lt;/code&gt;'s, and compare the biggest their worst in term of number of comparisons result to the expected maximal number of comparisons. If it exceeds this number, your implementation is not correct yet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frkybhst9aud4l1i18jth.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frkybhst9aud4l1i18jth.png" alt="Tester demonstration" width="800" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/emuminov/ford-jonson-tester" rel="noopener noreferrer"&gt;I also wrote a single-file testing script&lt;/a&gt; for benchmarking the algorithm. It requires your executable to print a sorted sequence and number of comparisons at the end of program.&lt;/p&gt;

&lt;p&gt;This is an example of how I count the number of comparisons in my code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;//////////// ADD COMPARISON COUNTER ////////////&lt;/span&gt;
&lt;span class="c1"&gt;// PmergeMe.hpp&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PmergeMe&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;public:&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;nbr_of_comps&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;_comp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;lv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;rv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;PmergeMe&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;nbr_of_comps&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;lv&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;rv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// PmergeMe.cpp don't forget to initialise it!&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;PmergeMe&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;nbr_of_comps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;//////////// USE _comp FOR COMPARISONS ////////////&lt;/span&gt;
&lt;span class="c1"&gt;// PmergeMe.hpp&lt;/span&gt;
&lt;span class="c1"&gt;// ... at the step 1&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_comp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next_pair&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;this_pair&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;_swap_pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;this_pair&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pair_level&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="c1"&gt;// ... at the step 3 whenever I search a place for a number to insert into&lt;/span&gt;
            &lt;span class="k"&gt;typename&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Iterator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;iterator&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;upper_bound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;bound_it&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pend_it&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_comp&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Iterator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The code
&lt;/h2&gt;

&lt;p&gt;I have implemented this algorithm in the context of doing the last C++ exercise of module 09, in the 42 school; and you may find my take on this algorithm &lt;a href="https://github.com/emuminov/cpp_modules" rel="noopener noreferrer"&gt;here&lt;/a&gt;, in cpp09/ex02. There are many ways to do this algorithm, my way is optimised for vectors and benefits a lot from random access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Last note
&lt;/h2&gt;

&lt;p&gt;Thank you &lt;a href="https://github.com/Emmatosorus" rel="noopener noreferrer"&gt;epolitze&lt;/a&gt; for proofreading the first version of the article, &lt;a href="https://github.com/sponthus" rel="noopener noreferrer"&gt;sponthus&lt;/a&gt; for proofreading the second edition, and &lt;a href="https://github.com/Celiastral" rel="noopener noreferrer"&gt;eandre&lt;/a&gt; for helping me to update the diagrams.&lt;br&gt;
This is a second version of an article, where I simplified some explanations (hopefully made them more clear) and fixed a mistake which was pointed out by &lt;a href="https://dev.to/bewerner/comment/2lj99"&gt;bwerner&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Original description of the algorithm, when runs out of the Jacobsthal numbers, inserts elements from &lt;code&gt;the pend&lt;/code&gt; in the reverse order, and in the previous version of the article I said that this doesn't make a difference according to my benchmarks; I was wrong! After writing the tester that rigorously tests ranges of numbers many-many times I found out that actually it matters whether it's in order or in reverse order. With this algorithm I had to run into unexplored waters, as there were no accessible articles or videos at the time of me doing the algorithm.&lt;/p&gt;

</description>
      <category>mergeinsertionsort</category>
      <category>fordjohnsonalgorithm</category>
      <category>42school</category>
      <category>cpp09</category>
    </item>
  </channel>
</rss>
