Open In App

Introduction to Smooth Sort

Smooth sort is a sorting algorithm that was introduced by Edsger Dijkstra. It is another version of heapsort that is designed to minimize the number of comparisons performed during the sort. Like heapsort, smooth sort sorts an array by building a heap and repeatedly extracting the maximum element.

Approach: Smooth sort approach is as follows:



  • Define the Leonardo numbers. 
  • Build the Leonardo heap by merging pairs of adjacent trees. 
    • Initialize p to the last index in the array. 
    •  Initialize q and r to p. 
    • While p > 0
         If the size of the subtree rooted at r is p, increment r. 
         Otherwise, decrement r, update q, and heapify the subtree rooted at r. 
         Swap the root element of the heap (at index 0) with the element at index p. 
         Decrement p. 
  • Convert the Leonardo heap back into an array.  For each pair of adjacent elements in the array: 
    • If the second element is smaller than the first, swap them. 
    • Iterate through the array in reverse order, swapping each pair of adjacent elements that are out of order.

Working of Smooth sort:

Using the Leonardo numbers, create initial Leonardo heaps by finding the largest Leonardo number that is less than or equal to n, and splitting the list into two sublists such that the first sublist has a length equal to the preceding Leonardo number and the second sublist has length equal to the preceding two Leonardo numbers.   
Sublist 1: [1, 7, 8]
Sublist 2: [2, 3, 5, 4, 6]
   
Iteration 1:
   Heap 1: [8]
   Heap 2: [7, 1]
   Heap 3: [6, 5, 4, 3, 2]



Iteration 2:
   Heap 1: [8, 7, 1]
   Heap 2: [6, 5, 4, 3, 2]

Iteration 3:
   Heap 1: [8, 7, 1, 6, 5, 4, 3, 2]

Sorted List: [8, 7, 6, 5, 4, 3, 2, 1]

Below is the implementation of the code:




// C++ implementation
 
#include <iostream>
#include <vector>
 
using namespace std;
 
// Define the Leonardo numbers
int leonardo(int k)
{
    if (k < 2) {
        return 1;
    }
    return leonardo(k - 1) + leonardo(k - 2) + 1;
}
 
// Build the Leonardo heap by merging
// pairs of adjacent trees
void heapify(vector<int>& arr, int start, int end)
{
    int i = start;
    int j = 0;
    int k = 0;
 
    while (k < end - start + 1) {
        if (k & 0xAAAAAAAA) {
            j = j + i;
            i = i >> 1;
        }
        else {
            i = i + j;
            j = j >> 1;
        }
 
        k = k + 1;
    }
 
    while (i > 0) {
        j = j >> 1;
        k = i + j;
        while (k < end) {
            if (arr[k] > arr[k - i]) {
                break;
            }
            swap(arr[k], arr[k - i]);
            k = k + i;
        }
 
        i = j;
    }
}
 
// Smooth Sort function
vector<int> smooth_sort(vector<int>& arr)
{
    int n = arr.size();
 
    int p = n - 1;
    int q = p;
    int r = 0;
 
    // Build the Leonardo heap by merging
    // pairs of adjacent trees
    while (p > 0) {
        if ((r & 0x03) == 0) {
            heapify(arr, r, q);
        }
 
        if (leonardo(r) == p) {
            r = r + 1;
        }
        else {
            r = r - 1;
            q = q - leonardo(r);
            heapify(arr, r, q);
            q = r - 1;
            r = r + 1;
        }
 
        swap(arr[0], arr[p]);
        p = p - 1;
    }
 
    // Convert the Leonardo heap
    // back into an array
    for (int i = 0; i < n - 1; i++) {
        int j = i + 1;
        while (j > 0 && arr[j] < arr[j - 1]) {
            swap(arr[j], arr[j - 1]);
            j = j - 1;
        }
    }
 
    return arr;
}
 
// Driver code
int main()
{
    vector<int> arr = { 1, 7, 8, 2, 3, 5, 4, 6 };
 
    // Original Array
    cout << "Input:   ";
    for (int i = 0; i < arr.size(); i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
 
    // Function call
    arr = smooth_sort(arr);
 
    // Sorted Array
    cout << "Output:  ";
    for (int i = 0; i < arr.size(); i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
 
    return 0;
}




# Python Implementation
 
 
def smooth_sort(arr):
    n = len(arr)
 
    # Define the Leonardo numbers
    def leonardo(k):
        if k < 2:
            return 1
        return leonardo(k - 1) + leonardo(k - 2) + 1
 
    # Build the Leonardo heap by merging
    # pairs of adjacent trees
    def heapify(start, end):
        i = start
        j = 0
        k = 0
 
        while k < end - start + 1:
            if k & 0xAAAAAAAA:
                j = j + i
                i = i >> 1
            else:
                i = i + j
                j = j >> 1
 
            k = k + 1
 
        while i > 0:
            j = j >> 1
            k = i + j
            while k < end:
                if arr[k] > arr[k - i]:
                    break
                arr[k], arr[k - i] = arr[k - i], arr[k]
                k = k + i
 
            i = j
 
    # Build the Leonardo heap by merging
    # pairs of adjacent trees
    p = n - 1
    q = p
    r = 0
    while p > 0:
        if (r & 0x03) == 0:
            heapify(r, q)
 
        if leonardo(r) == p:
            r = r + 1
        else:
            r = r - 1
            q = q - leonardo(r)
            heapify(r, q)
            q = r - 1
            r = r + 1
 
        arr[0], arr[p] = arr[p], arr[0]
        p = p - 1
 
    # Convert the Leonardo heap
    # back into an array
    for i in range(n - 1):
        j = i + 1
        while j > 0 and arr[j] < arr[j - 1]:
            arr[j], arr[j - 1] = arr[j - 1], arr[j]
            j = j - 1
 
    return arr
 
 
# Driver ccode
arr = [1, 7, 8, 2, 3, 5, 4, 6]
 
# Original Array
print('Input:   ', arr)
 
# Function call
print("Output:  ", smooth_sort(arr))




// C# code for the approach
 
using System;
using System.Collections.Generic;
 
public class SmoothSort {
    // Define the Leonardo numbers
    private static int Leonardo(int k) {
        if (k < 2) {
            return 1;
        }
        return Leonardo(k - 1) + Leonardo(k - 2) + 1;
    }
 
    // Build the Leonardo heap by merging
    // pairs of adjacent trees
    private static void Heapify(List<int> arr, int start, int end) {
        int i = start;
        int j = 0;
        int k = 0;
 
        while (k < end - start + 1) {
            if ((k & 0xAAAAAAAA) == 0xAAAAAAAA) {
                j += i;
                i >>= 1;
            } else {
                i += j;
                j >>= 1;
            }
 
            k++;
        }
 
        while (i > 0) {
            j >>= 1;
            int l = i + j;
            while (l < end) {
                if (arr[l] > arr[l - i]) {
                    break;
                }
                int temp = arr[l];
                arr[l] = arr[l - i];
                arr[l - i] = temp;
                l += i;
            }
 
            i = j;
        }
    }
 
    // Smooth Sort function
    public static List<int> Sort(List<int> arr) {
        int n = arr.Count;
 
        int p = n - 1;
        int q = p;
        int r = 0;
 
        // Build the Leonardo heap by merging
        // pairs of adjacent trees
        while (p > 0) {
            if ((r & 0x03) == 0) {
                Heapify(arr, r, q);
            }
 
            if (Leonardo(r) == p) {
                r++;
            } else {
                r--;
                q -= Leonardo(r);
                Heapify(arr, r, q);
                q = r - 1;
                r++;
            }
 
            int temp = arr[0];
            arr[0] = arr[p];
            arr[p] = temp;
            p--;
        }
 
        // Convert the Leonardo heap
        // back into an array
        for (int i = 0; i < n - 1; i++) {
            int j = i + 1;
            while (j > 0 && arr[j] < arr[j - 1]) {
                int temp = arr[j];
                arr[j] = arr[j - 1];
                arr[j - 1] = temp;
                j--;
            }
        }
 
        return arr;
    }
 
    // Driver code
    public static void Main() {
        List<int> arr = new List<int> { 1, 7, 8, 2, 3, 5, 4, 6 };
 
        // Original Array
        Console.Write("Input:   ");
        foreach (int num in arr) {
            Console.Write(num + " ");
        }
        Console.WriteLine();
 
        // Function call
        arr = Sort(arr);
 
        // Sorted Array
        Console.Write("Output:  ");
        foreach (int num in arr) {
            Console.Write(num + " ");
        }
        Console.WriteLine();
    }
}




// Define the Leonardo numbers
function leonardo(k) {
  if (k < 2) {
    return 1;
  }
  return leonardo(k - 1) + leonardo(k - 2) + 1;
}
 
// Build the Leonardo heap by merging
// pairs of adjacent trees
function heapify(arr, start, end) {
  let i = start;
  let j = 0;
  let k = 0;
 
  while (k < end - start + 1) {
    if (k & 0xAAAAAAAA) {
      j = j + i;
      i = i >> 1;
    } else {
      i = i + j;
      j = j >> 1;
    }
 
    k = k + 1;
  }
 
  while (i > 0) {
    j = j >> 1;
    k = i + j;
    while (k < end) {
      if (arr[k] > arr[k - i]) {
        break;
      }
      [arr[k], arr[k - i]] = [arr[k - i], arr[k]];
      k = k + i;
    }
 
    i = j;
  }
}
 
// Smooth Sort function
function smooth_sort(arr) {
  const n = arr.length;
 
  let p = n - 1;
  let q = p;
  let r = 0;
 
  // Build the Leonardo heap by merging
  // pairs of adjacent trees
  while (p > 0) {
    if ((r & 0x03) == 0) {
      heapify(arr, r, q);
    }
 
    if (leonardo(r) == p) {
      r = r + 1;
    } else {
      r = r - 1;
      q = q - leonardo(r);
      heapify(arr, r, q);
      q = r - 1;
      r = r + 1;
    }
 
    [arr[0], arr[p]] = [arr[p], arr[0]];
    p = p - 1;
  }
 
  // Convert the Leonardo heap
  // back into an array
  for (let i = 0; i < n - 1; i++) {
    let j = i + 1;
    while (j > 0 && arr[j] < arr[j - 1]) {
      [arr[j], arr[j - 1]] = [arr[j - 1], arr[j]];
      j = j - 1;
    }
  }
 
  return arr;
}
 
// Driver code
function main() {
  const arr = [1, 7, 8, 2, 3, 5, 4, 6];
 
  // Original Array
  console.log("Input:   " + arr.join(" "));
 
  // Function call
  const sortedArr = smooth_sort(arr);
 
  // Sorted Array
  console.log("Output:  " + sortedArr.join(" "));
}
 
main();




// Java implementation
import java.util.Arrays;
 
public class SmoothSort {
 
    // Define the Leonardo numbers
    static int leonardo(int k)
    {
        if (k < 2) {
            return 1;
        }
        return leonardo(k - 1) + leonardo(k - 2) + 1;
    }
 
    // Build the Leonardo heap by merging
    // pairs of adjacent trees
    static void heapify(int[] arr, int start, int end)
    {
        int i = start;
        int j = 0;
        int k = 0;
 
        while (k < end - start + 1) {
            if ((k & 0xAAAAAAAA) != 0) {
                j = j + i;
                i = i >> 1;
            }
            else {
                i = i + j;
                j = j >> 1;
            }
 
            k = k + 1;
        }
 
        while (i > 0) {
            j = j >> 1;
            k = i + j;
            while (k < end) {
                if (arr[k] > arr[k - i]) {
                    break;
                }
                int temp = arr[k];
                arr[k] = arr[k - i];
                arr[k - i] = temp;
                k = k + i;
            }
 
            i = j;
        }
    }
 
    // Smooth Sort function
    static int[] smoothSort(int[] arr)
    {
        int n = arr.length;
 
        int p = n - 1;
        int q = p;
        int r = 0;
 
        // Build the Leonardo heap by merging
        // pairs of adjacent trees
        while (p > 0) {
            if ((r & 0x03) == 0) {
                heapify(arr, r, q);
            }
 
            if (leonardo(r) == p) {
                r = r + 1;
            }
            else {
                r = r - 1;
                q = q - leonardo(r);
                heapify(arr, r, q);
                q = r - 1;
                r = r + 1;
            }
 
            int temp = arr[0];
            arr[0] = arr[p];
            arr[p] = temp;
            p = p - 1;
        }
 
        // Convert the Leonardo heap
        // back into an array
        for (int i = 0; i < n - 1; i++) {
            int j = i + 1;
            while (j > 0 && arr[j] < arr[j - 1]) {
                int temp = arr[j];
                arr[j] = arr[j - 1];
                arr[j - 1] = temp;
                j = j - 1;
            }
        }
 
        return arr;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int[] arr = { 1, 7, 8, 2, 3, 5, 4, 6 };
 
        // Original Array
        System.out.print("Input:   ");
        System.out.println(Arrays.toString(arr));
 
        // Function call
        arr = smoothSort(arr);
 
        // Sorted Array
        System.out.print("Output:  ");
        System.out.println(Arrays.toString(arr));
    }
}

Output
Input:    [1, 7, 8, 2, 3, 5, 4, 6]
Output:   [1, 2, 3, 4, 5, 6, 7, 8]

Time Complexity: O(nlogn), where n is the size of the input.
Auxiliary Space: O(1)

Advantages of Smooth Sort:

Disadvantages of Smooth Sort:

Why Smooth Sort Better Than Other Sorting Algorithms?


Article Tags :