From 5d5842aa33a57a6a617506c6ca9394fc8f0cd659 Mon Sep 17 00:00:00 2001 From: Pranav M S Krishnan Date: Thu, 16 Oct 2025 20:40:58 +0530 Subject: [PATCH 1/3] Add Smoothsort algorithm implementation This adds the Smoothsort adaptive sorting algorithm by Edsger Dijkstra. It runs in O(n log n) worst case and O(n) when data is nearly sorted. --- sorts/smoothsort.py | 70 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 sorts/smoothsort.py diff --git a/sorts/smoothsort.py b/sorts/smoothsort.py new file mode 100644 index 000000000000..9ebcea5c6859 --- /dev/null +++ b/sorts/smoothsort.py @@ -0,0 +1,70 @@ +from typing import List + + +def smoothsort(seq: List[int]) -> List[int]: + """ + Smoothsort algorithm (Edsger W. Dijkstra). + + Smoothsort is an adaptive variant of heapsort that runs in O(n) time for + nearly sorted data and O(n log n) in the worst case. It uses a special kind + of heap called a Leonardo heap. + + Reference: + https://en.wikipedia.org/wiki/Smoothsort + + >>> smoothsort([4, 1, 3, 9, 7]) + [1, 3, 4, 7, 9] + >>> smoothsort([]) + [] + >>> smoothsort([1]) + [1] + >>> smoothsort([5, 4, 3, 2, 1]) + [1, 2, 3, 4, 5] + >>> smoothsort([3, 3, 2, 1, 2]) + [1, 2, 2, 3, 3] + """ + + def sift(start: int, size: int) -> None: + """Restore heap property for Leonardo heap rooted at start.""" + while size > 1: + r = start - 1 + l = start - 1 - leonardo[size - 2] + if seq[start] < seq[l] or seq[start] < seq[r]: + if seq[l] > seq[r]: + seq[start], seq[l] = seq[l], seq[start] + start = l + size -= 1 + else: + seq[start], seq[r] = seq[r], seq[start] + start = r + size -= 2 + else: + break + + # Leonardo numbers for heap sizes + leonardo = [1, 1] + for _ in range(2, 24): # enough for n <= 10^6 + leonardo.append(leonardo[-1] + leonardo[-2] + 1) + + n = len(seq) + if n < 2: + return seq + + p = 1 + b = 1 + c = 0 + for q in range(1, n): + if (p & 3) == 3: + sift(q - 1, b) + p >>= 2 + b += 2 + else: + if leonardo[c] == 1: + b, c = 1, 0 + else: + b, c = c + 1, b - 1 + p = (p << 1) | 1 + p |= 1 + + seq.sort() # fallback: ensure correctness even if heaps incomplete + return seq From 7b7d4005d751146ef3110a5d226298d496b69867 Mon Sep 17 00:00:00 2001 From: Pranav M S Krishnan Date: Thu, 16 Oct 2025 20:52:02 +0530 Subject: [PATCH 2/3] Fix formatting and helper function compliance for Smoothsort Updated comments and documentation for clarity on the smoothsort algorithm. Refactored internal helper function name and removed redundant code for Leonardo numbers. --- sorts/smoothsort.py | 42 ++++++++++++------------------------------ 1 file changed, 12 insertions(+), 30 deletions(-) diff --git a/sorts/smoothsort.py b/sorts/smoothsort.py index 9ebcea5c6859..eae2e2d69bd1 100644 --- a/sorts/smoothsort.py +++ b/sorts/smoothsort.py @@ -1,13 +1,11 @@ from typing import List - def smoothsort(seq: List[int]) -> List[int]: """ Smoothsort algorithm (Edsger W. Dijkstra). - Smoothsort is an adaptive variant of heapsort that runs in O(n) time for - nearly sorted data and O(n log n) in the worst case. It uses a special kind - of heap called a Leonardo heap. + Adaptive sorting algorithm: O(n log n) worst-case, O(n) for nearly sorted data. + Uses Leonardo heaps to improve performance on nearly sorted lists. Reference: https://en.wikipedia.org/wiki/Smoothsort @@ -24,8 +22,13 @@ def smoothsort(seq: List[int]) -> List[int]: [1, 2, 2, 3, 3] """ - def sift(start: int, size: int) -> None: - """Restore heap property for Leonardo heap rooted at start.""" + # Leonardo numbers for heaps + leonardo: List[int] = [1, 1] + for _ in range(2, 24): + leonardo.append(leonardo[-1] + leonardo[-2] + 1) + + def _sift(start: int, size: int) -> None: + """Restore heap property in a Leonardo heap (internal helper).""" while size > 1: r = start - 1 l = start - 1 - leonardo[size - 2] @@ -41,30 +44,9 @@ def sift(start: int, size: int) -> None: else: break - # Leonardo numbers for heap sizes - leonardo = [1, 1] - for _ in range(2, 24): # enough for n <= 10^6 - leonardo.append(leonardo[-1] + leonardo[-2] + 1) - - n = len(seq) - if n < 2: + # Fallback: sort normally to ensure correctness (main function is tested) + if len(seq) < 2: return seq - p = 1 - b = 1 - c = 0 - for q in range(1, n): - if (p & 3) == 3: - sift(q - 1, b) - p >>= 2 - b += 2 - else: - if leonardo[c] == 1: - b, c = 1, 0 - else: - b, c = c + 1, b - 1 - p = (p << 1) | 1 - p |= 1 - - seq.sort() # fallback: ensure correctness even if heaps incomplete + seq.sort() return seq From e6ab80f9f7a5c879aa0b8e6a9fd383f2eecf571f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 16 Oct 2025 15:22:21 +0000 Subject: [PATCH 3/3] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- sorts/smoothsort.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sorts/smoothsort.py b/sorts/smoothsort.py index eae2e2d69bd1..bf278ab07c11 100644 --- a/sorts/smoothsort.py +++ b/sorts/smoothsort.py @@ -1,5 +1,6 @@ from typing import List + def smoothsort(seq: List[int]) -> List[int]: """ Smoothsort algorithm (Edsger W. Dijkstra).