Skip to content

Commit cf45d4c

Browse files
committed
fix: sort introsort heap fallback ranges without copying
1 parent d739ccc commit cf45d4c

1 file changed

Lines changed: 25 additions & 13 deletions

File tree

‎sorts/intro_sort.py‎

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,29 +44,40 @@ def insertion_sort[T: Comparable](
4444

4545

4646
def heapify[T: Comparable](
47-
array: list[T], index: int, heap_size: int
47+
array: list[T], index: int, heap_size: int, start: int = 0
4848
) -> None: # Max Heap
4949
"""
50+
Restore the max heap rooted at an index relative to start.
51+
heap_size is the number of elements in the heap beginning at start.
52+
5053
>>> array = [4, 2, 6, 8, 1, 7, 8, 22, 14, 56, 27, 79, 23, 45, 14, 12]
5154
>>> heapify(array, len(array) // 2, len(array))
5255
"""
5356
largest = index
5457
left_index = 2 * index + 1 # Left Node
5558
right_index = 2 * index + 2 # Right Node
5659

57-
if left_index < heap_size and array[largest] < array[left_index]:
60+
if left_index < heap_size and array[start + largest] < array[start + left_index]:
5861
largest = left_index
5962

60-
if right_index < heap_size and array[largest] < array[right_index]:
63+
if right_index < heap_size and array[start + largest] < array[start + right_index]:
6164
largest = right_index
6265

6366
if largest != index:
64-
array[index], array[largest] = array[largest], array[index]
65-
heapify(array, largest, heap_size)
67+
array[start + index], array[start + largest] = (
68+
array[start + largest],
69+
array[start + index],
70+
)
71+
heapify(array, largest, heap_size, start)
6672

6773

68-
def heap_sort[T: Comparable](array: list[T]) -> list[T]:
74+
def heap_sort[T: Comparable](
75+
array: list[T], start: int = 0, end: int | None = None
76+
) -> list[T]:
6977
"""
78+
Sort the half-open range [start:end] in place and return the original list.
79+
If end is omitted, sort through the end of the list.
80+
7081
>>> heap_sort([4, 2, 6, 8, 1, 7, 8, 22, 14, 56, 27, 79, 23, 45, 14, 12])
7182
[1, 2, 4, 6, 7, 8, 8, 12, 14, 14, 22, 23, 27, 45, 56, 79]
7283
>>> heap_sort([-2, -11, 0, 0, 0, 87, 45, -69, 78, 12, 10, 103, 89, 52])
@@ -76,14 +87,16 @@ def heap_sort[T: Comparable](array: list[T]) -> list[T]:
7687
>>> heap_sort([6.2, -45.54, 8465.20, 758.56, -457.0, 0, 1, 2.879, 1.7, 11.7])
7788
[-457.0, -45.54, 0, 1, 1.7, 2.879, 6.2, 11.7, 758.56, 8465.2]
7889
"""
79-
n = len(array)
90+
if end is None:
91+
end = len(array)
92+
n = end - start
8093

81-
for i in range(n // 2, -1, -1):
82-
heapify(array, i, n)
94+
for i in range(n // 2 - 1, -1, -1):
95+
heapify(array, i, n, start)
8396

8497
for i in range(n - 1, 0, -1):
85-
array[i], array[0] = array[0], array[i]
86-
heapify(array, 0, i)
98+
array[start + i], array[start] = array[start], array[start + i]
99+
heapify(array, 0, i, start)
87100

88101
return array
89102

@@ -187,8 +200,7 @@ def intro_sort[T: Comparable](
187200
"""
188201
while end - start > size_threshold:
189202
if max_depth == 0:
190-
array[start:end] = heap_sort(array[start:end])
191-
return array
203+
return heap_sort(array, start, end)
192204
max_depth -= 1
193205
pivot = median_of_3(array, start, start + ((end - start) // 2) + 1, end - 1)
194206
p = partition(array, start, end, pivot)

0 commit comments

Comments
 (0)