algoalgo-world
algoalgo-world/sort/smooth-sort
sort/smooth-sort

Smooth Sort

best
O(n)
average
O(n log n)
worst
O(n log n)
space
O(1)
stability
unstable
method
comparison

pick a language to open the code

LEO = [1, 1]
while len(LEO) < 40:
    LEO.append(LEO[-1] + LEO[-2] + 1)


def trinkle(a, orders, j, r):
    k = orders[j]
    while j > 0:
        prev = r - LEO[k]
        big = max(a[r], a[r - 1], a[r - 1 - LEO[k - 2]]) if k >= 2 else a[r]
        if a[prev] <= big:
            break
        a[r], a[prev] = a[prev], a[r]
        j -= 1
        r, k = prev, orders[j]
    while k >= 2:
        left = r - 1 - LEO[k - 2]
        child, step = (r - 1, 2) if a[r - 1] >= a[left] else (left, 1)
        if a[r] >= a[child]:
            return
        a[r], a[child] = a[child], a[r]
        r, k = child, k - step


def smooth_sort(a):
    orders = []
    for i in range(len(a)):
        if len(orders) >= 2 and orders[-2] == orders[-1] + 1:
            orders.pop()
            orders[-1] += 1
        else:
            orders.append(0 if orders and orders[-1] == 1 else 1)
        trinkle(a, orders, len(orders) - 1, i)
    for i in range(len(a) - 1, 0, -1):
        k = orders.pop()
        if k >= 2:
            orders.append(k - 1)
            trinkle(a, orders, len(orders) - 1, i - 1 - LEO[k - 2])
            orders.append(k - 2)
            trinkle(a, orders, len(orders) - 1, i - 1)
const LEO = [1, 1];
while (LEO.length < 40) LEO.push(LEO.at(-1) + LEO.at(-2) + 1);

function trinkle(a, orders, j, r) {
  let k = orders[j];
  while (j > 0) {
    const prev = r - LEO[k];
    let big = a[r];
    if (k >= 2) big = Math.max(big, a[r - 1], a[r - 1 - LEO[k - 2]]);
    if (a[prev] <= big) break;
    [a[r], a[prev]] = [a[prev], a[r]];
    [r, k] = [prev, orders[--j]];
  }
  while (k >= 2) {
    const left = r - 1 - LEO[k - 2];
    const child = a[r - 1] >= a[left] ? r - 1 : left;
    if (a[r] >= a[child]) return;
    [a[r], a[child]] = [a[child], a[r]];
    k -= child === r - 1 ? 2 : 1;
    r = child;
  }
}

function smoothSort(a) {
  const orders = [];
  for (let i = 0; i < a.length; i++) {
    if (orders.length >= 2 && orders.at(-2) === orders.at(-1) + 1) {
      orders.pop();
      orders[orders.length - 1]++;
    } else {
      orders.push(orders.at(-1) === 1 ? 0 : 1);
    }
    trinkle(a, orders, orders.length - 1, i);
  }
  for (let i = a.length - 1; i > 0; i--) {
    const k = orders.pop();
    if (k < 2) continue;
    orders.push(k - 1);
    trinkle(a, orders, orders.length - 1, i - 1 - LEO[k - 2]);
    orders.push(k - 2);
    trinkle(a, orders, orders.length - 1, i - 1);
  }
}
static const int LEO[] = {1, 1, 3, 5, 9, 15, 25, 41, 67, 109, 177, 287, 465,
    753, 1219, 1973, 3193, 5167, 8361, 13529, 21891, 35421, 57313, 92735};

static void trinkle(int a[], int orders[], int j, int r) {
    int k = orders[j];
    while (j > 0) {
        int prev = r - LEO[k];
        int big = a[r];
        if (k >= 2 && a[r - 1] > big) big = a[r - 1];
        if (k >= 2 && a[r - 1 - LEO[k - 2]] > big) big = a[r - 1 - LEO[k - 2]];
        if (a[prev] <= big) break;
        int t = a[r]; a[r] = a[prev]; a[prev] = t;
        r = prev;
        k = orders[--j];
    }
    while (k >= 2) {
        int left = r - 1 - LEO[k - 2];
        int child = a[r - 1] >= a[left] ? r - 1 : left;
        if (a[r] >= a[child]) return;
        int t = a[r]; a[r] = a[child]; a[child] = t;
        k -= child == r - 1 ? 2 : 1;
        r = child;
    }
}

void smooth_sort(int a[], int n) {
    int orders[24];
    int top = -1;
    for (int i = 0; i < n; i++) {
        if (top >= 1 && orders[top - 1] == orders[top] + 1) orders[--top]++;
        else if (top >= 0 && orders[top] == 1) orders[++top] = 0;
        else orders[++top] = 1;
        trinkle(a, orders, top, i);
    }
    for (int i = n - 1; i > 0; i--) {
        int k = orders[top--];
        if (k < 2) continue;
        orders[++top] = k - 1;
        trinkle(a, orders, top, i - 1 - LEO[k - 2]);
        orders[++top] = k - 2;
        trinkle(a, orders, top, i - 1);
    }
}
static const int LEO[] = {1, 1, 3, 5, 9, 15, 25, 41, 67, 109, 177, 287, 465,
    753, 1219, 1973, 3193, 5167, 8361, 13529, 21891, 35421, 57313, 92735};

static void trinkle(std::vector<int>& a, const int orders[], int j, int r) {
    int k = orders[j];
    while (j > 0) {
        int prev = r - LEO[k];
        int big = a[r];
        if (k >= 2) big = std::max({big, a[r - 1], a[r - 1 - LEO[k - 2]]});
        if (a[prev] <= big) break;
        std::swap(a[r], a[prev]);
        r = prev;
        k = orders[--j];
    }
    while (k >= 2) {
        int left = r - 1 - LEO[k - 2];
        int child = a[r - 1] >= a[left] ? r - 1 : left;
        if (a[r] >= a[child]) return;
        std::swap(a[r], a[child]);
        k -= child == r - 1 ? 2 : 1;
        r = child;
    }
}

void smooth_sort(std::vector<int>& a) {
    int n = static_cast<int>(a.size());
    int orders[24];
    int top = -1;
    for (int i = 0; i < n; i++) {
        if (top >= 1 && orders[top - 1] == orders[top] + 1) orders[--top]++;
        else if (top >= 0 && orders[top] == 1) orders[++top] = 0;
        else orders[++top] = 1;
        trinkle(a, orders, top, i);
    }
    for (int i = n - 1; i > 0; i--) {
        int k = orders[top--];
        if (k < 2) continue;
        orders[++top] = k - 1;
        trinkle(a, orders, top, i - 1 - LEO[k - 2]);
        orders[++top] = k - 2;
        trinkle(a, orders, top, i - 1);
    }
}
static readonly int[] Leo = {1, 1, 3, 5, 9, 15, 25, 41, 67, 109, 177, 287,
    465, 753, 1219, 1973, 3193, 5167, 8361, 13529, 21891, 35421, 57313, 92735};

static void Trinkle(int[] a, int[] orders, int j, int r) {
    int k = orders[j];
    while (j > 0) {
        int prev = r - Leo[k];
        int big = a[r];
        if (k >= 2) big = Math.Max(big, a[r - 1]);
        if (k >= 2) big = Math.Max(big, a[r - 1 - Leo[k - 2]]);
        if (a[prev] <= big) break;
        (a[r], a[prev]) = (a[prev], a[r]);
        r = prev;
        k = orders[--j];
    }
    while (k >= 2) {
        int left = r - 1 - Leo[k - 2];
        int child = a[r - 1] >= a[left] ? r - 1 : left;
        if (a[r] >= a[child]) return;
        (a[r], a[child]) = (a[child], a[r]);
        k -= child == r - 1 ? 2 : 1;
        r = child;
    }
}

static void SmoothSort(int[] a) {
    int[] orders = new int[Leo.Length];
    int top = -1;
    for (int i = 0; i < a.Length; i++) {
        if (top >= 1 && orders[top - 1] == orders[top] + 1) orders[--top]++;
        else if (top >= 0 && orders[top] == 1) orders[++top] = 0;
        else orders[++top] = 1;
        Trinkle(a, orders, top, i);
    }
    for (int i = a.Length - 1; i > 0; i--) {
        int k = orders[top--];
        if (k < 2) continue;
        orders[++top] = k - 1;
        Trinkle(a, orders, top, i - 1 - Leo[k - 2]);
        orders[++top] = k - 2;
        Trinkle(a, orders, top, i - 1);
    }
}
static final int[] LEO = {1, 1, 3, 5, 9, 15, 25, 41, 67, 109, 177, 287, 465,
    753, 1219, 1973, 3193, 5167, 8361, 13529, 21891, 35421, 57313, 92735};

static void trinkle(int[] a, int[] orders, int j, int r) {
    int k = orders[j];
    while (j > 0) {
        int prev = r - LEO[k];
        int big = a[r];
        if (k >= 2) big = Math.max(big, a[r - 1]);
        if (k >= 2) big = Math.max(big, a[r - 1 - LEO[k - 2]]);
        if (a[prev] <= big) break;
        int t = a[r]; a[r] = a[prev]; a[prev] = t;
        r = prev;
        k = orders[--j];
    }
    while (k >= 2) {
        int left = r - 1 - LEO[k - 2];
        int child = a[r - 1] >= a[left] ? r - 1 : left;
        if (a[r] >= a[child]) return;
        int t = a[r]; a[r] = a[child]; a[child] = t;
        k -= child == r - 1 ? 2 : 1;
        r = child;
    }
}

static void smoothSort(int[] a) {
    int[] orders = new int[LEO.length];
    int top = -1;
    for (int i = 0; i < a.length; i++) {
        if (top >= 1 && orders[top - 1] == orders[top] + 1) orders[--top]++;
        else if (top >= 0 && orders[top] == 1) orders[++top] = 0;
        else orders[++top] = 1;
        trinkle(a, orders, top, i);
    }
    for (int i = a.length - 1; i > 0; i--) {
        int k = orders[top--];
        if (k < 2) continue;
        orders[++top] = k - 1;
        trinkle(a, orders, top, i - 1 - LEO[k - 2]);
        orders[++top] = k - 2;
        trinkle(a, orders, top, i - 1);
    }
}
watch it run, then read it