Quick sort
Algorithm
def quick(a):
"""
Implements the quick sort algorithm.
"""
def sort(a,low,high):
if high <= low:
return
j = partition(a,low,high)
sort(a,low,j-1)
sort(a,j+1,high)
def partition(a,low,high):
pivot = a[low]
i = low+1
j = high
while True:
while a[i] < pivot and i < high:
i = i + 1
while pivot < a[j] and j > low:
j = j - 1
if i >= j:
break
temp = a[i]
a[i] = a[j]
a[j] = temp
temp = a[low]
a[low] = a[j]
a[j] = temp
return j
sort(a, 0, len(a)-1)
return a
Step by step
array = [1,0,3,4,2,5]
sort(array, 0, 5)
partition(array, 0, 5) | array = [0,1,3,4,2,5]
sort(array, 0, 0)
sort(array, 2, 5)
partition(array, 2, 5) | array = [0,1,2,3,4,5]
We will now see in detail the calls to the partition
function.
partition(a, 0, 5)
------------------
a = [1,0,3,4,2,5]
low = 0
high = 5
pivot = a[0] | pivot = 1
i = 1
j = 5
while True
while a[1] < 1 and 1 < 5 | False
while pivot < a[5] and 5 > 0 | pivot < 5 | True
j = j - 1 | j = 4
while pivot < a[4] and 5 > 0 | pivot < 5 | True
j = j - 1 | j = 3
while pivot < a[3] and 5 > 0 | pivot < 5 | True
j = j - 1 | j = 2
while pivot < a[2] and 5 > 0 | pivot < 5 | True
j = j - 1 | j = 1
while pivot < a[1] and 5 > 0 | pivot < 5 | False
i >= j | 1 >= 1 | True
temp = a[0]
a[0] = a[1]
a[1] = temp | a = [0,1,3,4,2,5]
return 1
partition(a, 2, 5)
------------------
a = [1,0,3,4,2,5]
low = 2
high = 5
pivot = a[2] | pivot = 3
i = 3
j = 5
while True
while a[3] < 3 and 3 < 5 | False
while 3 < a[5] and 5 > 2 | True
j = j - 1 | j = 4
while 3 < a[4] and 4 > 2 | False
i >= j | 3 >= 4 | False
temp = a[3]
a[3] = a[4]
a[4] = temp | a = [0,1,3,2,4,5]
while a[3] < 3 and 3 < 5 | True
i = i + 1 | i = 4
while a[4] < 3 and 3 < 5 | False
while 4 < a[4] and 4 > 2 | True
j = j - 1 | j = 3
while 4 < a[3] and 3 > 2 | False
i >= j | 4 >= 3 | True
temp = a[2]
a[2] = a[3]
a[3] = a[2] | a = [0,1,2,3,4,5]
Complexity analysis
Time
Worst-case
The worst-case happens when the pivot is, in every recrsive call, the biggest (or the smallest) element. When this happens, for the first call we go through N elements, for the second call we go through N - 1 elements and for the last call we go through 2 elements. This is: N + (N - 1) + (N - 2) + … + 2.
So the cost is: O(N) = N²
Best-case
The best-case happens when the pivot is, in every recursive call, the middle of the rest of elements. When this happens, we are splitting in two the size of the array in every call.
So the cost is: O(N) = N · log N
Average case
Average case: O(N) = 2N · ln N = 2N · (log N / log e) = (2N / log e) · log N ≈ 1.39N log N.
Space
Each call to either partition or
sort` uses a few variables. Since there will be log N calls the amount of space it takes is:
O(N) = N + log N.
Use cases
This algorithm is useful for sorting big arrays with not a lot of repeated elements.