# sorting algorithms import random def swap(A, i, j): if i != j: A[i], A[j] = A[j], A[i] # See: http://en.wikipedia.org/wiki/Bubble_sort#Pseudocode_implementation def bubbleSort(A): numComp = numAccess = 0 n = len(A) swapped = True while swapped and n > 1: swapped = False for i in range(1, n): numAccess += 2 numComp += 1 if A[i-1] > A[i]: numAccess += 2 # two writes by swap (A[i-1], A[i] already read) swap(A, i-1, i) swapped = True n -= 1 return { "number of compares" : numComp, "number of accesses" : numAccess, } # See: http://en.wikipedia.org/wiki/Selection_sort def selectionSort(A): numComp = numAccess = 0 n = len(A) for i in range(0, n-1): k = i numAccess += 1 a = A[k] for j in range(i+1, n): numAccess += 1 b = A[j] numComp += 1 if b < a: k = j a = b if i != k: numAccess += 3 # two writes + read A[i] by swap swap(A, i, k) return { "number of compares" : numComp, "number of accesses" : numAccess, } # See: http://en.wikipedia.org/wiki/Insertion_sort#Algorithm def insertionSort(A): numComp = numAccess = 0 n = len(A) for i in range(1, n): numAccess += 1 a = A[i] j = i while j > 0: numAccess += 1 b = A[j-1] numComp += 1 if a < b: numAccess += 1 A[j] = b j -= 1 else: break numAccess += 1 A[j] = a return { "number of compares" : numComp, "number of accesses" : numAccess, } # See: http://en.wikipedia.org/wiki/Quicksort#In-place_version def quickSort(A): global numComp, numAccess numComp = numAccess = 0 def partition(A, left, right, pivotIndex): global numComp, numAccess numAccess += 4 # two writes + two reads by swap pivotValue = A[pivotIndex] swap(A, pivotIndex, right) storeIndex = left for i in range(left, right): numAccess += 1 numComp += 1 if A[i] < pivotValue: if i != storeIndex: numAccess += 3 # two writes + one read by swap (A[i] already read) swap(A, i, storeIndex) # TODO maybe we don't need swap here, just shift storeIndex += 1 if storeIndex != right: numAccess += 4 # two writes + two reads by swap swap(A, storeIndex, right) return storeIndex def qsort(A, left, right): if left < right: pivotIndex = random.randint(left, right) pivotNewIndex = partition(A, left, right, pivotIndex) qsort(A, left, pivotNewIndex-1) qsort(A, pivotNewIndex+1, right) qsort(A, 0, len(A)-1) return { "number of compares" : numComp, "number of accesses" : numAccess, } # See: http://en.wikipedia.org/wiki/Merge_sort#Bottom-up_implementation def mergeSort(C): global numComp, numAccess numComp = numAccess = 0 def merge(A, left, right, end, B): global numComp, numAccess i = left j = right for k in range(left, end): numAccess += 2 # always one read (A[i] or A[j]) and a write (to B[k]) use_x = False if i < right: x = A[i] if j >= end: use_x = True else: numAccess += 1 # A[j] also read y = A[j] numComp += 1 if x <= y: use_x = True else: y = A[j] if use_x: B[k] = x i += 1 else: B[k] = y j += 1 A = C N = len(A) B = N * [None] width = 1 while width < N: for i in range(0, N, 2*width): merge(A, i, min(i+width, N), min(i+2*width, N), B) A, B = B, A width *= 2 C[:] = A return { "number of compares" : numComp, "number of accesses" : numAccess, }