# Mergesort - includes mergesort and merge functions # ECS10 - Spring 2009 # Justin Cummins #Importing random for the shuffle function import random # Selection sort by Prof. Matt Bishop, ECS10 - Spring 2009 #Given list of values, #selsort returns the list values in sorted order, O(N**2) def selsort(lst): # go through the list # each (outer) loop puts the smallest number # at the head of the list beginning with the # given index n = len(lst) for i in range(n-1): # assume smallest is already at head of list mp = i # look for a smaller number in the rest of the list for j in range(i+1, n): # if it's smaller, remember where it is if lst[mp] > lst[j]: mp = j # now swap the smallest to the head lst[i], lst[mp] = lst[mp], lst[i] #Merge function, recursive version, O(N) # Maximum recursion depth error may occur for very large inputs #Input: Two sorted lists #Returns: a sorted list, combination of input lists def merge_rec(listA, listB): #print "Debug: Calling merge(%s, %s)" % (listA, listB) #If either list empty, return the other #Concatenating the empty list has no effect if listA == [] or listB == []: return listA + listB #Set helper variables for first values of each list firstA, firstB = listA[0], listB[0] #Return the smaller concatenated with the merge of everything #else if firstA < firstB: return [firstA] + merge(listA[1:], listB) else: return [firstB] + merge(listA, listB[1:]) #Merge function, iterative version, O(N) #Input: Two sorted lists #Returns: a sorted list, combination of input lists def merge_iter(listA, listB): #Initialize variables result = [] indexA, indexB = 0, 0 #Denotes index under examination #Continue until one list is empty while indexA < len(listA) and indexB < len(listB): #If current listA value less than current listB value if listA[indexA] < listB[indexB]: #Put the smaller on the result, and move past it result.append(listA[indexA]) indexA += 1 else: #Put the smaller on the result, and move past it result.append(listB[indexB]) indexB += 1 #One index reached the end, append remaining values to result if indexA >= len(listA): result += listB[indexB:] #Values left in listB still else: result += listA[indexA:] #Values left in listA still return result #Mergesort function, recursive # O(N*logN) relies on merge function #Input: list of comparable values #Returns: list with input values in sorted order def mergesort(values): #print "Calling mergesort(%s)" % values #Already sorted when zero or one value in list if len(values) == 1 or len(values) == 0: return values #Find halfway point and partition # if odd num of values, one "half" is larger by one half = len(values)/2 partA, partB = values[:half], values[half:] #Recursively sort each half partA = mergesort(partA) partB = mergesort(partB) #Merge the two sorted halves, return result return merge_iter(partA, partB) #Main function # Asks user for number of values to sort, generates random list, # sorts list using mergesort then selection sort. def main(): n = raw_input("How many numbers should I generate for sorting? ") try: n = int(n) except ValueError: print "Please enter a valid number next time." return values = range(n) #ordered list from 0 to n-1 #Shuffle is a slow operation, randomly shuffles list order random.shuffle(values) #Printing list of values is very slow when n is large print "Mergesort --" #print "Original list:", values values2 = mergesort(values) print "Mergesort Done!" #print "Sorted list:", values2 print print "Selectionsort --" #print "Original list:", values values2 = selsort(values) print "Selection sort Done!" #print "Sorted list:", values2 main()