0% found this document useful (0 votes)
10 views60 pages

CS1033 L10 Search Sort

Uploaded by

Dulan Madushanka
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views60 pages

CS1033 L10 Search Sort

Uploaded by

Dulan Madushanka
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 60

CS1033 Programming Fundamentals

Searching and Sorting

Eng Dr Chandana Gamage


BSc Eng Hons, MEng, PhD, CEng
Department of Computer Science & Engineering
University of Moratuwa

October 15, 2022

1 / 46
Acknowledgment

These lecture notes are based on the course textbook Problem


Solving with Algorithms and Data Structures using Python by
Bradley N. Miller, David L. Ranum, 2013.

2 / 46
Contents

◮ Introduction

3 / 46
Contents

◮ Introduction
◮ Searching algorithms
◮ Sequential search
◮ Binary search

3 / 46
Contents

◮ Introduction
◮ Searching algorithms
◮ Sequential search
◮ Binary search
◮ Sorting algorithms
◮ Bubble sort
◮ Selection sort
◮ Insertion sort
◮ Shell sort
◮ Merge sort
◮ Quick sort
◮ Heap sort

3 / 46
Introduction

Searching for data and sorting of data is at the core of solving


many problems.

4 / 46
Introduction

Searching for data and sorting of data is at the core of solving


many problems.

◮ A search algorithms typically will provide a Boolean answer


to the question if a particular data item is present in a
collection data items.
◮ A search algorithm may also provide the location of data
item in the collection if it is an ordered collection.
◮ Different algorithms for searching and sorting have different
performance characteristics related to running time, memory
usage, and performance stability.
◮ Every search or sort algorithm requires a comparison
function for the items in the collection (typically the
operators >, < and == is used).

4 / 46
Sequential Search

The sequential search algorithm can be used to search for an item


in any iterable collection.

5 / 46
Sequential Search

The sequential search algorithm can be used to search for an item


in any iterable collection.

◮ The algorithm is simple to implement, easy to understand but


most often highly inefficient.
◮ The performance can be analyzed using number of
comparisons used in a sequential search of an unordered list
with n items.
Case Best Worst Average
n
Item found 1 n 2
Item not found n n n

5 / 46
Iterative Sequential Search
1 def sequential_search(a_list, item):
2 pos = 0
3 found = False
4
5 while pos < len(a_list) and not found:
6 if a_list[pos] == item:
7 found = True
8 else:
9 pos = pos+1
10
11 if found:
12 return pos
13 else:
14 return -1
15
16 test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42,]
17 print(sequential_search(test_list, 3))
6 / 46
Recursive Sequential Search

1 def sequential_search_rec(a_list, item):


2 if len(a_list) == 0:
3 return False
4 elif a_list[0] == item:
5 return True
6 else:
7 return sequential_search_rec(a_list[1:], item)
8
9 test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42,]
10 print(sequential_search_rec(test_list, 3))

7 / 46
Binary Search
The binary search algorithm can be used to search for an item in
any ordered collection such as a list.

8 / 46
Binary Search
The binary search algorithm can be used to search for an item in
any ordered collection such as a list.

◮ The algorithm is simple to implement, easy to understand and


highly efficient.
◮ It works by comparing the middle item in the list and
deciding to further search in either left or right half of the list.
◮ This algorithm is an example of the divide and conquer
strategy as well as the recursive problem solving approach.
◮ The performance analysis of the algorithm must consider the
cost of sorting the collection, which could be considerably
high for a large collection of items.
◮ While sorting a collection once and searching in it many times
may appear an advantageous approach, a careful analysis is
required of the sorting cost and cost savings obtained for a
particular number of searches.
8 / 46
Iterative Binary Search
1 def binary_search(a_list, item):
2 first = 0
3 last = len(a_list) - 1
4 found = False
5
6 while first <= last and not found:
7 mid = (first + last) // 2
8 if a_list[mid] == item:
9 found = True
10 else:
11 if item < a_list[mid]:
12 last = mid - 1 # search in first half
13 else:
14 first = mid + 1 # search in second half
15
16 if found:
17 return mid
18 else:
19 return -1
20 test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42,]
21 print(binary_search(test_list, 3))
9 / 46
Recursive Binary Search

1 def binary_search_rec(a_list, item):


2 if len(a_list) == 0:
3 return False
4 else:
5 mid = len(a_list) // 2
6 if a_list[mid] == item:
7 return True
8 else:
9 if item < a_list[mid]:
10 return binary_search_rec(a_list[:mid], item)
11 else:
12 return binary_search_rec(a_list[mid + 1:], item)
13
14 test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42,]
15 print(binary_search_rec(test_list, 3))

10 / 46
Recursive binary search examples

3 ? [0, 1, 2, 8, 13, 17, 19, 32, 42]


3 ? [0, 1, 2, 8]
3 ? [8]
3 ? []
False

32 ? [0, 1, 2, 8, 13, 17, 19, 32, 42]


32 ? [17, 19, 32, 42]
True

42 ? [0, 1, 2, 8, 13, 17, 19, 32, 42]


42 ? [17, 19, 32, 42]
42 ? [42]
True

11 / 46
Time Complexities of Search Algorithms

Algorithm Best Average Worst


Sequential Search O(1) O(n) O(n)
Binary Search O(1) O(log n) O(log n)

12 / 46
Sorting

A sorting algorithm reorganizes a collection of items into some


order as defined by values intrinsic to the items such as numerical
order, alphabetical order, item length, etc.

13 / 46
Sorting

A sorting algorithm reorganizes a collection of items into some


order as defined by values intrinsic to the items such as numerical
order, alphabetical order, item length, etc.

◮ Sorting algorithms use two operations that are central to the


analysis of their performance:
1. Comparison of items to determine their relative order (≤ or
≥)
2. Rearrangement of items to change their order of appearance
in the collection (usually done through a swap() operation)
◮ The total number of comparisons and swapping performed
would provide the means of comparing different sorting
algorithms.

13 / 46
Bubble Sort 1/2
The bubble sort algorithm makes multiple passes through a
collection and compare adjacent items to reorder those that are
out of order.

14 / 46
Bubble Sort 1/2
The bubble sort algorithm makes multiple passes through a
collection and compare adjacent items to reorder those that are
out of order.

◮ Each pass through the list would place the next largest item
at its correct position while reducing the size of the remaining
collection to be sorted by one.
◮ Bubble sort will make n − 1 passes to sort a list of n items
and the total
Pn−1number of comparisons is the sum of first n − 1
integers ( i=1 i = n(n−1)
2 = 12 n2 − 21 n).
◮ Bubble sort will make no swaps in the best case (for an
already ordered list) and a swap for every comparison in the
worst case (for a collection sorted in the reverse order).
◮ An improvement of this algorithm is to terminate it early if
there were no swaps performed during a pass through the list,
which indicate that the list is sorted in order at that point.
14 / 46
Bubble Sort (iterative) 2/2

1 def bubble_sort(a_list):
2 # outer loop
3 for j in range(len(a_list) - 1, 0, -1):
4 # inner loop
5 for i in range(j):
6 if a_list[i] > a_list[i + 1]:
7 # do a swap
8 temp = a_list[i]
9 a_list[i] = a_list[i + 1]
10 a_list[i + 1] = temp
11
12 a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20]
13 bubble_sort(a_list)
14 print(a_list)

15 / 46
Selection Sort 1/2

The selection sort algorithm is an improvement over the bubble


sort algorithm where only one swapping of values done for each
pass through the list.

16 / 46
Selection Sort 1/2

The selection sort algorithm is an improvement over the bubble


sort algorithm where only one swapping of values done for each
pass through the list.

◮ For this purpose, the algorithm keeps track of the position of


the highest value encountered through a pass over the list and
after completing the pass perform the swap operation to
correctly place the item.
◮ While the selection sort makes the same total number of
comparisons as the bubble sort ( 12 n2 − 12 n for a list of n
items), the number of swaps may get greatly reduced as it will
make only n number of swaps.

16 / 46
Selection Sort (iterative) 2/2
1 def selection_sort(a_list):
2 # outer loop
3 for j in range(len(a_list) - 1, 0, -1):
4 pos_of_max = 0
5 # inner loop
6 for i in range(1, j + 1):
7 if a_list[i] > a_list[pos_of_max]:
8 pos_of_max = i
9 # do a swap
10 temp = a_list[j]
11 a_list[j] = a_list[pos_of_max]
12 a_list[pos_of_max] = temp
13
14 a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20]
15 selection_sort(a_list)
16 print(a_list)
17 / 46
Selection sort example

start [54, 26, 93, 17, 77, 31, 44, 55, 20]
pass 8 [54, 26, 20, 17, 77, 31, 44, 55, 93]
pass 7 [54, 26, 20, 17, 55, 31, 44, 77, 93]
pass 6 [54, 26, 20, 17, 44, 31, 55, 77, 93]
pass 5 [31, 26, 20, 17, 44, 54, 55, 77, 93]
pass 4 [31, 26, 20, 17, 44, 54, 55, 77, 93]
pass 3 [17, 26, 20, 31, 44, 54, 55, 77, 93]
pass 2 [17, 20, 26, 31, 44, 54, 55, 77, 93]
pass 1 [17, 20, 26, 31, 44, 54, 55, 77, 93]

18 / 46
Selection sort example

19 / 46
Insertion Sort 1/2

The insertion sort algorithm works by maintaining a sorted sublist


in the lower positions in the list.

20 / 46
Insertion Sort 1/2

The insertion sort algorithm works by maintaining a sorted sublist


in the lower positions in the list.

◮ Each new item picked from the unsorted sublist is then


inserted back into the sorted sublist such that the sorted
sublist is one item longer.
◮ On each pass, the current item being checked is compared
against those values in the sorted sublist. Items greater than
the item being checked are shifted to the right.
◮ When a smaller item is reached or the end of the sublist is
reached, the current item is inserted to the correct position.
◮ In the worst case, the insertion sort will make 12 n2 − 21 n
comparisons for a list of n items and in the best case only one
comparison on each pass for a total of n − 1 comparisons.

20 / 46
Insertion Sort (iterative) 2/2
1 def insertion_sort(a_list):
2 for index in range(1, len(a_list)):
3 current_value = a_list[index]
4 pos = index
5
6 while pos > 0 and a_list[pos - 1] > current_value:
7 a_list[pos] = a_list[pos - 1]
8 pos = pos - 1
9
10 a_list[pos] = current_value
11
12 a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20]
13 insertion_sort(a_list)
14 print(a_list)

Insertion sort performs shift operations rather than swap operations


making it much faster as only a single assignment is required (in
comparison to 3 assignments for a swap).
21 / 46
Insertion sort example

start [54, 26, 93, 17, 77, 31, 44, 55, 20]
pass 1 [26, 54, 93, 17, 77, 31, 44, 55, 20]
pass 2 [26, 54, 93, 17, 77, 31, 44, 55, 20]
pass 3 [17, 26, 54, 93, 77, 31, 44, 55, 20]
pass 4 [17, 26, 54, 77, 93, 31, 44, 55, 20]
pass 5 [17, 26, 31, 54, 77, 93, 44, 55, 20]
pass 6 [17, 26, 31, 44, 54, 77, 93, 55, 20]
pass 7 [17, 26, 31, 44, 54, 55, 77, 93, 20]
pass 8 [17, 20, 26, 31, 44, 54, 55, 77, 93]

22 / 46
Insertion sort example

23 / 46
Shell Sort 1/3

The shell sort algorithm is an improvement over the insertion sort


by breaking the original list into a number of smaller sublists, each
of which is sorted using an insertion sort.

24 / 46
Shell Sort 1/3

The shell sort algorithm is an improvement over the insertion sort


by breaking the original list into a number of smaller sublists, each
of which is sorted using an insertion sort.

◮ Shell sort uses an increment value, gap, to create a sublist by


choosing all items that are gap number of items apart.
◮ When the initial set of sublists are sorted, although the list
items are not yet in their final correct positions, they have
moved closer to those positions.
◮ A final insertion sort using an increment of one will place all
the items into their correct positions.
◮ The advantage of shell sort is that the previous sublist sorts
reduce the total number of shift operations necessary to put
the list in its final order.

24 / 46
Shell Sort (iterative) 2/3

1 def shell_sort(a_list):
2 sublist_count = len(a_list) // 2
3
4 while sublist_count > 0:
5 for start_pos in range(sublist_count):
6 gap_insertion_sort(a_list,start_pos,sublist_count)
7
8 print("After increments of size", sublist_count,
"The list is",a_list)
9
10 sublist_count = sublist_count // 2
11

25 / 46
Shell Sort (iterative) 3/3

12 def gap_insertion_sort(a_list, start, gap):


13 for i in range(start + gap, len(a_list), gap):
14 current_value = a_list[i]
15 pos = i
16
17 while pos >= gap and a_list[pos-gap] > current_value:
18 a_list[pos] = a_list[pos - gap]
19 pos = pos - gap
20
21 a_list[pos] = current_value
22
23 a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20]
24 shell_sort(a_list)
25 print(a_list)

26 / 46
Shell sort example
sort [54, 26, 93, 17, 77, 31, 44, 55, 20] with sublist size 4
4 [54, 26, 93, 17, 77, 31, 44, 55, 20]
8 [20, 26, 93, 17, 54, 31, 44, 55, 77]
5 [20, 26, 93, 17, 54, 31, 44, 55, 77]
6 [20, 26, 44, 17, 54, 31, 93, 55, 77]
7 [20, 26, 44, 17, 54, 31, 93, 55, 77]
sort [20, 26, 44, 17, 54, 31, 93, 55, 77] with sublist size 2
2 [20, 26, 44, 17, 54, 31, 93, 55, 77]
4 [20, 26, 44, 17, 54, 31, 93, 55, 77]
6 [20, 26, 44, 17, 54, 31, 93, 55, 77]
8 [20, 26, 44, 17, 54, 31, 77, 55, 93]
3 [20, 17, 44, 26, 54, 31, 77, 55, 93]
5 [20, 17, 44, 26, 54, 31, 77, 55, 93]
7 [20, 17, 44, 26, 54, 31, 77, 55, 93]
sort [20, 17, 44, 26, 54, 31, 77, 55, 93] with sublist size 1
1 [17, 20, 44, 26, 54, 31, 77, 55, 93]
2 [17, 20, 44, 26, 54, 31, 77, 55, 93]
3 [17, 20, 26, 44, 54, 31, 77, 55, 93]
4 [17, 20, 26, 44, 54, 31, 77, 55, 93]
5 [17, 20, 26, 31, 44, 54, 77, 55, 93]
6 [17, 20, 26, 31, 44, 54, 77, 55, 93]
7 [17, 20, 26, 31, 44, 54, 55, 77, 93]
8 [17, 20, 26, 31, 44, 54, 55, 77, 93]

27 / 46
Shell sort example

28 / 46
Merge Sort 1/3
Merge sort is a recursive algorithm that continually splits a list in
half.

29 / 46
Merge Sort 1/3
Merge sort is a recursive algorithm that continually splits a list in
half.

◮ If the list is empty or has one item, it is sorted by definition


(the base case).
◮ If the list has more than one item, the list is split and a merge
sort is recursively invoked on both halves (the recursive
case).
◮ Once the two halves are sorted, the merge operation is
performed, which is the process of taking two smaller sorted
lists and combining them together into a single, sorted, new
list.
◮ The analysis of merge sort algorithm must consider the
number of times a list of n items can be split in half (log n)
and the number of operations required to merge a list of n
items (n), resulting in a total of n log n operations.
29 / 46
Merge Sort (recursive) 2/3
1 def merge_sort(a_list):
2 print("Splitting ", a_list)
3 if len(a_list) > 1:
4 mid = len(a_list) // 2
5 left_half = a_list[:mid]
6 right_half = a_list[mid:]
7
8 merge_sort(left_half)
9 merge_sort(right_half)
10
11 i = 0; j = 0; k = 0
12
13 while i < len(left_half) and j < len(right_half):
14 if left_half[i] < right_half[j]:
15 a_list[k] = left_half[i]
16 i = i + 1
30 / 46
Merge Sort (recursive) 3/3
17 else:
18 a_list[k] = right_half[j]
19 j = j + 1;
20 k = k + 1
21
22 while i < len(left_half):
23 a_list[k] = left_half[i]
24 i = i + 1; k = k + 1
25
26 while j < len(right_half):
27 a_list[k] = right_half[j]
28 j = j + 1; k = k + 1
29
30 print("Merging ", a_list)
31
32 a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20]
33 merge_sort(a_list); print(a_list)
31 / 46
Merge sort example
Splitting [12, 11, 13, 5, 6]
Splitting [12, 11]
Splitting [12]
Merging [12]
Splitting [11]
Merging [11]
Merging [11, 12]
Splitting [13, 5, 6]
Splitting [13]
Merging [13]
Splitting [5, 6]
Splitting [5]
Merging [5]
Splitting [6]
Merging [6]
Merging [5, 6]
Merging [5, 6, 13]
Merging [5, 6, 11, 12, 13]

32 / 46
Merge sort - splitting example

33 / 46
Merge sort - merging example

34 / 46
Quick Sort 1/3
Quick sort is a recursive algorithm that use the divide and conquer
strategy to continually split a list around a selected value called the
split point.

35 / 46
Quick Sort 1/3
Quick sort is a recursive algorithm that use the divide and conquer
strategy to continually split a list around a selected value called the
split point.

◮ Quick sort algorithm first selects a value called the pivot


value (for example, the first value in the list) to begin the
process of splitting the list.
◮ The actual position where the pivot value belongs in the final
sorted list is the split point used to divide the list.
◮ Before splitting, a partition process will move items less than
pivot value to it’s left and items greater than or equal to right.
◮ The analysis of quick sort algorithm must consider the number
of times a list of n items can be split (if done in the middle, it
will be log n) and the number of comparison operations with
pivot value required to find the split point of a list of n items
(n operations), resulting in a total of n log n operations.
35 / 46
Quick Sort (recursive) 2/3
1 def quick_sort(a_list, first, last):
2 if first < last:
3 split_point = partition(a_list, first, last)
4 quick_sort(a_list, first, split_point - 1)
5 quick_sort(a_list, split_point + 1, last)
6
7 def partition(a_list, first, last):
8 pivot_value = a_list[first]
9 left_mark = first + 1
10 right_mark = last
11 done = False
12
13 while not done:
14 while left_mark <= right_mark and
a_list[left_mark] <= pivot_value:
15 left_mark = left_mark + 1
16
17 while a_list[right_mark] >= pivot_value and
right_mark >= left_mark:
18 right_mark = right_mark - 1 36 / 46
Quick Sort (recursive) 3/3
19
20 if right_mark < left_mark:
21 done = True
22 else:
23 temp = a_list[left_mark]
24 a_list[left_mark] = a_list[right_mark]
25 a_list[right_mark] = temp
26
27 temp = a_list[first]
28 a_list[first] = a_list[right_mark]
29 a_list[right_mark] = temp
30
31 return right_mark
32
33 a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20]
34 quick_sort(a_list, 0, len(a_list) - 1)
35 print(a_list)
37 / 46
Quick sort example
[54, 26, 93, 17, 77, 31, 44, 55, 20] 0 8
partitioned at 5
[31, 26, 20, 17, 44, 54, 77, 55, 93] 0 4
partitioned at 3
[17, 26, 20, 31, 44, 54, 77, 55, 93] 0 2
partitioned at 0
[17, 26, 20, 31, 44, 54, 77, 55, 93] 0 -1
no partition
[17, 26, 20, 31, 44, 54, 77, 55, 93] 1 2
partitioned at 2
[17, 20, 26, 31, 44, 54, 77, 55, 93] 1 1
no partition
[17, 20, 26, 31, 44, 54, 77, 55, 93] 3 2
no partition
[17, 20, 26, 31, 44, 54, 77, 55, 93] 4 4
no partition
[17, 20, 26, 31, 44, 54, 77, 55, 93] 6 8
partitioned at 7
[17, 20, 26, 31, 44, 54, 55, 77, 93] 6 6
no partition
[17, 20, 26, 31, 44, 54, 55, 77, 93] 8 8
no partition 38 / 46
Heap Sort 1/5

Heap sort is a comparison-based sorting technique based on


Binary Heap data structure.

39 / 46
Heap Sort 1/5

Heap sort is a comparison-based sorting technique based on


Binary Heap data structure.

◮ A binary heap data structure is based on the Complete


Binary Tree data structure.
◮ A complete binary tree is a Binary Tree in which every level,
except possibly the last, is completely filled, and all nodes are
as far left as possible.
◮ A binary heap is a complete binary tree where items are stored
in a specific order such that the value in a parent node is
greater (or smaller) than the values in its two children nodes.
◮ When the value in a parent node is greater than the values in
its two children nodes, it is called a max heap while the value
is smaller, it is called a min-heap.

39 / 46
Heap Sort 2/5

Binary heap can be represented by a binary tree or an array.

40 / 46
Heap Sort 2/5

Binary heap can be represented by a binary tree or an array.

◮ In array representation of a binary heap, if a parent node is


stored at index i, the left child is stored at index 2 × i + 1
and the right child is stored at index 2 × i + 2 (assuming the
indexing starts at 0).
◮ The array-based representation of a binary heap is
space-efficient.
◮ Heap sort is similar to selection sort where a search is done to
find the item with the minimum value and this item is placed
at the beginning of the list. The same process is repeated for
remaining items.

40 / 46
Heap Sort 3/5

◮ The heap sort algorithm has following steps:


1. Build a max heap from the input data.
2. At this point, the largest item is stored at the root of the heap.
Replace it with the last item of the heap followed by reducing
the size of heap by 1. Finally, heapify the root of the tree.
3. Repeat step 2 while the size of the heap is greater than 1.
◮ The heapify procedure can be applied to a node only if its
children nodes are heapified. So the heapification must be
performed in the bottom-up order.

41 / 46
Heap Sort 4/5
# To heapify subtree rooted at index i. Heap size is n.
def heapify(a_list, n, i):
largest = i # Initialize largest as root
l = 2 * i + 1 # left = 2*i + 1
r = 2 * i + 2 # right = 2*i + 2

# See if left child of root exists and is > root


if l < n and a_list[i] < a_list[l]:
largest = l

# See if right child of root exists and is > root


if r < n and a_list[largest] < a_list[r]:
largest = r

# Change root, if needed


if largest != i:
a_list[i],a_list[largest] = a_list[largest],a_list[i] # swap
# Heapify the root.
heapify(a_list, n, largest)
42 / 46
Heap Sort 5/5

def heap_sort(a_list):
n = len(a_list)

# Build a maxheap. Since last parent will be


# at ((n//2)-1) we can start at that location.
for i in range(n // 2 - 1, -1, -1):
heapify(a_list, n, i)

# One by one extract elements


for i in range(n-1, 0, -1):
a_list[i], a_list[0] = a_list[0], a_list[i] # swap
heapify(a_list, i, 0)

a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20]
heap_sort(a_list)
print(a_list)
43 / 46
Heap sort example
input
[54, 26, 93, 17, 77, 31, 44, 55, 20]
build max heap
[54, 26, 93, 55, 77, 31, 44, 17, 20]
[54, 26, 93, 55, 77, 31, 44, 17, 20]
[54, 77, 93, 55, 26, 31, 44, 17, 20]
[93, 77, 54, 55, 26, 31, 44, 17, 20]
progressively sort
[77, 55, 54, 20, 26, 31, 44, 17, 93]
[55, 26, 54, 20, 17, 31, 44, 77, 93]
[54, 26, 44, 20, 17, 31, 55, 77, 93]
[44, 26, 31, 20, 17, 54, 55, 77, 93]
[31, 26, 17, 20, 44, 54, 55, 77, 93]
[26, 20, 17, 31, 44, 54, 55, 77, 93]
[20, 17, 26, 31, 44, 54, 55, 77, 93]
[17, 20, 26, 31, 44, 54, 55, 77, 93]
[17, 20, 26, 31, 44, 54, 55, 77, 93]
44 / 46
Time Complexities of Sorting Algorithms

Algorithm Best Average Worst


Bubble Sort O(n) O(n2 ) O(n2 )
Selection Sort O(n2 ) O(n2 ) O(n2 )
Insertion Sort O(n) O(n2 ) O(n2 )
Shell Sort O(n) O((n log n)2 ) O((n log n)2 )
Merge Sort O(n log n) O(n log n) O(n log n)
Quick Sort O(n log n) O(n log n) O(n2 )
Heap Sort O(n log n) O(n log n) O(n log n)

45 / 46
Exercise
Implement the algorithms discussed in this lecture and test them
with following timing measurements code inserted.

1 import time
2
3 # the searching or sorting function
...
40 a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20]
41 print(a_list)
42 start_time = time.time()
43 function_name(a_list)
44 end_time = time.time() - start_time
45 print(a_list)
46 print("execution time is %s seconds" % end_time)

◮ Prepare a table of execution times for the algorithms and compare


the measured times against the theoretical values given in O(. . .)
notation.
46 / 46

You might also like