0% found this document useful (0 votes)
13 views12 pages

COL100-Lecture 14 Sorting

The document discusses the concept of ordered lists and various sorting algorithms, including selection sort, bubble sort, insertion sort, merge sort, and quicksort. It provides definitions, properties of ordered lists, and detailed implementations of each sorting algorithm in Python. Additionally, it includes exercises related to the properties of sorted lists and merging sorted lists.

Uploaded by

Jadugar Chirag
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)
13 views12 pages

COL100-Lecture 14 Sorting

The document discusses the concept of ordered lists and various sorting algorithms, including selection sort, bubble sort, insertion sort, merge sort, and quicksort. It provides definitions, properties of ordered lists, and detailed implementations of each sorting algorithm in Python. Additionally, it includes exercises related to the properties of sorted lists and merging sorted lists.

Uploaded by

Jadugar Chirag
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/ 12

Sorting

Ordered Lists
Given a set A, and a total ordering ≤ on A.

A list L of elements from A is called ordered or sorted according to ≤ on A if


forall i, j (0 ≤ i, j < len(L)): i < j implies L[ i ] ≤ L[ j ]

Properties
• [ ] is an ordered (or sorted) list
• Each singleton list [ a ] is a ordered (or sorted) list (for each a in A)
• If L is a sorted list, and x ≤ L[ i ] then x ≤ L[ j ] for all j ≥ i (0 ≤ i, j < len(L))
• If L is a sorted list, and x ≥ L[ i ] then x ≥ L[ j ] for all j ≤ i (0 ≤ i, j < len(L))
• If L1 and L2 are sorted lists of elements from A (ordered according to ≤ on A) such
that len(L1) = m, and if L1[ m-1 ] ≤ L2[ 0 ] then app(L1, L2) is a sorted list (ordered
according to ≤ on A)
• If L is a sorted list, element x in A such that for each j (0 ≤ i < len(L)): L[ j ] ≤ x, then
L.append(x) is sorted.

Exercise: Show that app(L1, L2) is sorted if L1[ m - 1] ≤ L2[ 0 ] where len(L1) = m

Exercise: If L is a sorted list ordered according ≤ on A, show that


rev(L) is a sorted list ordered according to ≥ on A
Sorting by Selection: program

# Sort a list in place


def selsort2(L):
# INPUT L : any list (L s.t. True)
# OUTPUT L is a permutation of Linit, L is sorted
# Initialisation
n = len(L)
# k is the barrier between the sorted and unsorted part
# Progressively move k from 0 to n
# INVARIANT: L is a permutation of Linit /\
# FORALL(0≤i,j<k): L[i] ≤ L[j] /\
# FORALL j(k≤j<n): L[k-1] ≤ L[j]
# Find the least element of L[k]..L[n-1]
# and Swap it into L[k]
# n-k step of this inner loop
# EXIT when k == n
# n iterations of outer for loop
return L
Sorting by Selection: program
# Sort a list in place
def selsort2(L):
# INPUT L : any list (L s.t. True)
# OUTPUT L is a permutation of Linit, L is sorted
# Initialisation
n = len(L)
for k in range (0,n):
# INVARIANT: L is a permutation of Linit /\
# FORALL(0≤i,j<k): L[i] ≤ L[j] /\
# FORALL j(k≤j<n): L[k-1] ≤ L[j]
# Find the least element of L[k]..L[n-1] moving it into L[k]
for i in range (k+1, n): # check if any other element is smaller
# INVARIANT: FORALL j(k≤j<i): L[k] ≤ L[j]
if (L[i] < L[k]): # found a smaller element
L[k], L[i] = L[i], L[k]
# EXIT: FORALL j(k≤j<n): L[minPos] ≤ L[j]
# n-k iterations of inner for loop
# EXIT when k == n
# n iterations of outer for loop
return L

>>> selsort2 ([4, 6, 1, 2, 7, 2, 3, 5, 4, 8, 9, 1, 3])


[1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9]
>>>
Selection by “Bubbling”
# Sort a list in place
def bubblesort(L):
# INPUT L : any list (L s.t. True)
# OUTPUT L is a permutation of Linit, L is sorted
# Initialisation
n = len(L)
for k in range (0,n):
# INVARIANT: L is a permutation of Linit /\
# FORALL(0≤i,j<k): L[i] ≤ L[j] /\
# FORALL j(k≤j<n): L[k-1] ≤ L[j]
# Find the least element of L[k]..L[n-1], swap it into L[k]
for i in range (n-1, k, -1):
# INVARIANT: FORALL j(i≤j<n): L[i] ≤ L[j]
# If right element is smaller than left
# Swap L[i-1] and L[i]
if (L[i] < L[i-1]):
L[i-1], L[i] = L[i], L[i-1]
# EXIT: FORALL j(k≤j<n): L[k] ≤ L[j]
# n-k iterations of inner for loop
# EXIT when k == n
# n iterations of outer for loop
return L
Sorting by Insertion: program

Like we do with a hand of cards

def insertionsort(L):
# INPUT L : any list (L s.t. True)
# OUTPUT L1 is a permutation of L, L1 is sorted
# Initialisation
n = len(L)
L1 = [ ]
# Maintain L1 as a sorted list
# Look at each element of L in turn (k in 0..n-1),
# insert L[k] into the right position in L1

# INVARIANT: FORALL(0≤i<k): L1[i] == L[j] for some (0≤j<k)


# /\ FORALL(0≤i,j<k): L1[i] ≤ L1[j]

# EXIT when k == n
# n iterations of outer for loop
return L1
Sorting by Insertion: program

def insertionsort_mistake(L):
# INPUT L : any list (L s.t. True)
# OUTPUT L1 is a permutation of L, L1 is sorted
# Initialisation
n = len(L)
L1 = [ ]
for k in range (0,n):
# INVARIANT: FORALL(0≤i<k): L1[i] == L[j] for some (0≤j<k)
# /\ FORALL(0≤i,j<k): L1[i] ≤ L1[j]
i = 0
while (i<k) & (L1[i] < L[k]): # FORALL(0≤j<i): L1[j]<L[k]
i += 1
# EXIT when L1[i] ≥ L[k]
# upto k iterations of inner while loop
L1.insert(i,L[k]) # Do not assume this is O(1)
# EXIT when k == n
# n iterations of outer for loop
return L1
Sorting by Insertion: correct program
def insertionsort(L):
# INPUT L : any list (L s.t. True)
# OUTPUT L is a permutation of Linit, L is sorted
# Initialisation
n = len(L)
L1 = [ ]
for k in range (0,n):
# INVARIANT: FORALL(0≤i<k): L1[i] == L[j] for some (0≤j<k)
# /\ FORALL(0≤i,j<k): L1[i] ≤ L1[j]
i = 0
posfound = False
while (i<k) & (not posfound): # FORALL(0≤j<i):L1[j]≤L[k]
if (L1[i] < L[k]):
i += 1
else:
posfound = True
# EXIT when L1[i] ≥ L[k] or i=k
# upto k iterations of inner while loop
L1.insert(i,L[k]) # What is the complexity?
# EXIT when k == n
# n iterations of outer for loop
return L1
Merging sorted lists: program
# Given two sorted lists L1 and L2, return a new sorted list L3
# that combine the elements of L1 and L2
# INPUT L1, L2 sorted lists
# OUTPUT L3 s.t L3 sorted list /\ L3 permutation of app(L1,L2)
def merge( L1, L2):
# Initialisation
L3 = [ ]
m = len(L1)
n = len(L2)
i = 0
j = 0
# INVARIANT for all k, h (0≤k,m≤i+j): k < m implies L3[k] ≤ L3[h]
# /\ for all k (i ≤k < m): L3[i+j] ≤ L1[k] /\
# /\ for all h (j ≤h < m): L3[i+j] ≤ L2[h]
while (i < m) & (j < n): # in each iteration either i or j increases by 1
if L1[i] <= L2[j]: # find the lower of L[i] and L[j] to copy over to L3
L3.append(L1[i])
i += 1
else:
L3.append(L2[j])
j+= 1
if (i == m):
while (j < n): # Copy remaining L2 elements
L3.append(L2[j])
j+= 1
else:
while (i < m): # Copy remaining L1 elements
L3.append(L1[i])
i += 1
return L3 # O(m+n)
Sorting by Merging
def mergesort(L):
# INPUT L : any list (L s.t. True)
# OUTPUT L3 is a permutation of L, L3 is sorted
n = len(L)
if (n <= 1 ): # L is already sorted
return L
else:
mid = n//2 # find mid point of list
# Divide the list in 2 roughly equal parts,
# Note: if we can’t do so, then not efficient
L1 = L[0:mid] # first “half”
L2 = L[mid:n] # second “half”
# recursively sort first half # T(n//2)
L1sort = mergesort(L1)
# recursively sort second half # T(n//2)
L2sort = mergesort(L2)
# merge sorted lists O(n//2 + n//2)
L3 = merge(L1sort, L2sort)
# T(n) = 2 T(n//2) + O(n)
return L3
Sorting by Partitioning

def quickSort(L, low, high):


# INPUT L : any list (L s.t. True)
# OUTPUT L is a sorted permutation of Linit
if len(L) <= 1: # already sorted
return L
if low < high: # non-trivial range to sort
# find the right position (partIndex) for a pivot element
# elements less than the pivot are to its left,
# those greater than to it on the right
partIndex = partition(L, low, high)
# pivot is now in the right place
# recursively sort the left and right partitions
quickSort(L, low, partIndex-1)
quickSort(L, partIndex+1, high)
Partitioning

def partition(L, low, high):


pivot = L[low] # pick pivot element e.g. leftmost
i = low+1
j = high
while True: # I HATE programming like this
# successively move left index rightwards until L[i] > pivot
while (i<=j) and L[i] <= pivot:
i += 1
# EXIT when L[i] > pivot
# successively move right index leftwards until L[j] < pivot
while (i<=j) and L[j] >= pivot:
j -= 1
# EXIT when L[j] < pivot
if (i <= j):
# Swap L[i], L[j]
L[i], L[j] = L[j], L[i]
else:
# Swap pivot and L[j], we know L[j] < pivot
L[low], L[j] = L[j], L[low]
# Now pivot is in the position partIndex posn j
return j

You might also like