Sorting Algorithms
Sorting Algorithms
Compares the first item in the list with second item and swaps them if
necessary. Then compares second and third item until end of the list. If all the
elements are compared it is in first pass, then the list is compared again for
second pass.
Time and Space complexities
When the array is already sorted, bubble sort is completed in single pass and
runs the loop once.
On average, each pair of elements are compared multiple times and requires to
run in loops.
def bubblesort(array):
for i in range(0, len(array)-1):
sorted = True
for j in range(0, len(array)-1):
if array[j]>array[j+1]:
array[j] , array[j+1] = array[j+1], array[j]
sorted = False
if sorted:
break
return array
array = [5, 0, 1, 34, 11, 10, 98 ,2,-1]
print(bubblesort(array))
Insertion Sort
When the array is already sorted, insertion sort is completed in single pass and runs the
loop once.
On average, each element is compared with about half of the sorted portion of the array
before being placed in its correct position
Requires a constant amount of additional memory space regardless of the size of the
array.
def insertion_sort(array):
Merge Sort
Splits the list in half and repeats until the elements in a pair. In pair, the elements are
compared and swap. Then this sorted pair is merge back with other pairs into one sorted
list.
Time and Space complexities
Sorting Algorithm Page 2
Time and Space complexities
The list still goes through the recursive process, even if the array is sorted.
On average, merge sort behaviour does not change and repeats the same splitting and
merging operation using recursion
Requires extra memory to perform merging and splitting operation by using temporary
arrays to store those pairs.
def mergesort(array):
if len(array) > 1:
mid = len(array) // 2 # Find the middle of the array
left_half = array[:mid] # Divide the array into two halves
right_half = array[mid:]
mergesort(left_half) # Recursively sort the left half
mergesort(right_half) # Recursively sort the right half
i = j = k = 0
# Copy data to temporary arrays left_half and right_half
while i < len(left_half) and j < len(right_half):
if left_half[i] < right_half[j]:
array[k] = left_half[i]
i += 1
else:
array[k] = right_half[j]
j += 1
k += 1
# Checking if any element was left
while i < len(left_half):
array[k] = left_half[i]
i += 1
k += 1
while j < len(right_half):
array[k] = right_half[j]
j += 1
k += 1
return array
Sorting Algorithm Page 3
return array
# Example usage:
array = [5, 0, 1, 34, 11, 10, 98 ,2,-1]
print(mergesort(array))
Quick Sort
Picks an item and call it the pivot. Split the list into two one less than the pivot and
one list where elements are greater than pivot. Then using recursion, splits the list
further into sub lists and then combines at the end.
Time and Space complexities
When the pivot divides the array into two nearly equal parts, the recursion depth is
minimized. Each level of recursion handles half of the elements.
On average, the pivot will split the array into parts that are not exactly equal but not
extremely unbalanced either.
The space complexity is primarily due to the recursive function calls. The depth of the
recursion tree depends on how balanced the partitions are and the depth of the
recursion tree is log(n), so the space complexity is O(log n).
def quicksort(array):
if len(array) <= 1:
return array
else:
pivot = array[0]
left = [x for x in array[1:] if x < pivot]
right = [x for x in array[1:] if x >= pivot]
return quicksort(left) + [pivot]+ quicksort(right)
array = [5, 0, 1, 34, 11, 10, 98 ,2,-1]
print(quicksort(array))