forked from TheAlgorithms/Python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathquick_sort.py
More file actions
86 lines (63 loc) · 2.49 KB
/
quick_sort.py
File metadata and controls
86 lines (63 loc) · 2.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
"""
A pure Python implementation of the quick sort algorithm
For doctests run following command:
python3 -m doctest -v quick_sort.py
For manual testing run:
python3 quick_sort.py
"""
from __future__ import annotations
from random import randrange
def quick_sort(collection: list) -> list:
"""A pure Python implementation of quicksort algorithm using in-place sorting.
:param collection: a mutable collection of comparable items
:return: the same collection ordered in ascending order
Examples:
>>> quick_sort([0, 5, 3, 2, 2])
[0, 2, 2, 3, 5]
>>> quick_sort([])
[]
>>> quick_sort([-2, 5, 0, -45])
[-45, -2, 0, 5]
"""
# Call the helper function to sort in-place
_quick_sort(collection, 0, len(collection) - 1)
return collection
def _quick_sort(collection: list, low: int, high: int) -> None:
"""Helper function that performs in-place quicksort.
:param collection: the list to sort
:param low: starting index of the partition
:param high: ending index of the partition
"""
if low < high:
# Partition the array and get the pivot index
pivot_index = _partition(collection, low, high)
# Recursively sort elements before and after partition
_quick_sort(collection, low, pivot_index - 1)
_quick_sort(collection, pivot_index + 1, high)
def _partition(collection: list, low: int, high: int) -> int:
"""In-place partitioning using Lomuto partition scheme.
:param collection: the list to partition
:param low: starting index of the partition
:param high: ending index of the partition
:return: the final pivot index after partitioning
"""
# Randomly select a pivot index and swap with the last element
pivot_index = randrange(low, high + 1)
# Use a temporary variable for the swap to keep lines short
temp_pivot = collection[pivot_index]
collection[pivot_index] = collection[high]
collection[high] = temp_pivot
pivot = collection[high]
# Index of smaller element (elements <= pivot will be moved to left of this)
i = low - 1
# Traverse through all elements and move smaller elements to the left
for j in range(low, high):
if collection[j] <= pivot:
i += 1
collection[i], collection[j] = collection[j], collection[i]
# Place pivot in its correct position
collection[i + 1], collection[high] = collection[high], collection[i + 1]
return i + 1
if __name__ == "__main__":
import doctest
doctest.testmod()