Introduction to Smooth Sort
Last Updated :
15 Apr, 2023
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.
- However, smooth sort uses a different data structure when compared to heap sort. Specifically, it uses a data structure called the Leonardo heap, which is a binary tree with the property that the root of each subtree has one fewer element than its parent.
- The shape of the Leonardo heap is determined by a sequence of numbers called the Leonardo.
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++
#include <iostream>
#include <vector>
using namespace std;
int leonardo( int k)
{
if (k < 2) {
return 1;
}
return leonardo(k - 1) + leonardo(k - 2) + 1;
}
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;
}
}
vector< int > smooth_sort(vector< int >& arr)
{
int n = arr.size();
int p = n - 1;
int q = p;
int r = 0;
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;
}
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;
}
int main()
{
vector< int > arr = { 1, 7, 8, 2, 3, 5, 4, 6 };
cout << "Input: " ;
for ( int i = 0; i < arr.size(); i++) {
cout << arr[i] << " " ;
}
cout << endl;
arr = smooth_sort(arr);
cout << "Output: " ;
for ( int i = 0; i < arr.size(); i++) {
cout << arr[i] << " " ;
}
cout << endl;
return 0;
}
|
Python3
def smooth_sort(arr):
n = len (arr)
def leonardo(k):
if k < 2 :
return 1
return leonardo(k - 1 ) + leonardo(k - 2 ) + 1
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
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
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
arr = [ 1 , 7 , 8 , 2 , 3 , 5 , 4 , 6 ]
print ( 'Input: ' , arr)
print ( "Output: " , smooth_sort(arr))
|
C#
using System;
using System.Collections.Generic;
public class SmoothSort {
private static int Leonardo( int k) {
if (k < 2) {
return 1;
}
return Leonardo(k - 1) + Leonardo(k - 2) + 1;
}
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;
}
}
public static List< int > Sort(List< int > arr) {
int n = arr.Count;
int p = n - 1;
int q = p;
int r = 0;
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--;
}
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;
}
public static void Main() {
List< int > arr = new List< int > { 1, 7, 8, 2, 3, 5, 4, 6 };
Console.Write( "Input: " );
foreach ( int num in arr) {
Console.Write(num + " " );
}
Console.WriteLine();
arr = Sort(arr);
Console.Write( "Output: " );
foreach ( int num in arr) {
Console.Write(num + " " );
}
Console.WriteLine();
}
}
|
Javascript
function leonardo(k) {
if (k < 2) {
return 1;
}
return leonardo(k - 1) + leonardo(k - 2) + 1;
}
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;
}
}
function smooth_sort(arr) {
const n = arr.length;
let p = n - 1;
let q = p;
let r = 0;
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;
}
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;
}
function main() {
const arr = [1, 7, 8, 2, 3, 5, 4, 6];
console.log( "Input: " + arr.join( " " ));
const sortedArr = smooth_sort(arr);
console.log( "Output: " + sortedArr.join( " " ));
}
main();
|
Java
import java.util.Arrays;
public class SmoothSort {
static int leonardo( int k)
{
if (k < 2 ) {
return 1 ;
}
return leonardo(k - 1 ) + leonardo(k - 2 ) + 1 ;
}
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;
}
}
static int [] smoothSort( int [] arr)
{
int n = arr.length;
int p = n - 1 ;
int q = p;
int r = 0 ;
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 ;
}
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;
}
public static void main(String[] args)
{
int [] arr = { 1 , 7 , 8 , 2 , 3 , 5 , 4 , 6 };
System.out.print( "Input: " );
System.out.println(Arrays.toString(arr));
arr = smoothSort(arr);
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:
- Smooth Sort is an adaptive sorting algorithm, meaning that it performs well on partially sorted lists.
- The algorithm has a time complexity of O(n log n), which is the same as merge sort and heap sort.
- Smooth Sort uses a small amount of extra memory and has a low memory overhead compared to other sorting algorithms, such as merge sort.
- The algorithm is stable, meaning that it preserves the relative order of equal elements in the list.
Disadvantages of Smooth Sort:
- Smooth Sort is a complex algorithm, and it is more difficult to implement than some other sorting algorithms, such as insertion sort.
- The algorithm requires the use of Leonardo numbers, which are a less well-known mathematical concept, so the algorithm may not be as widely used or understood as other algorithms.
Why Smooth Sort Better Than Other Sorting Algorithms?
- Smooth sort also has a low memory footprint compared to some other sorting algorithms. This can be important in situations where memory usage is a concern.
- Overall, while smooth sorting may not be the best choice for all sorting scenarios, it can be a good choice in situations where data is partially sorted or contains a large number of duplicates.
- Smooth sort is an adaptive sorting algorithm, meaning that it can adjust its behavior based on the characteristics of the input data. This allows smooth sorting to be more efficient than non-adaptive sorting algorithms in certain situations.
Share your thoughts in the comments
Please Login to comment...