""" A collection of sorting functions and code for timing them """ import random import time from matplotlib import pyplot def selection_sort(some_list): """ Sort the list in place using the selection sort algorithm""" # At each iteration, find the next smallest element in the list # and put it in the correct place for i in range(len(some_list)): # find the index of the smallest value from # i to the end min_index = i for j in range(i+1,len(some_list)): if some_list[j] < some_list[min_index]: min_index = j # swap i and min_index (some_list[i], some_list[min_index]) = \ (some_list[min_index], some_list[i]) def insertion_sort(some_list): """ Sort the list in place using the insertion sort algorithm """ for i in range(1,len(some_list)): # everything from 0...i-1 is sorted already # shift all the values up in 0...i-1 that are # larger than some_list[i] value = some_list[i] index = i while some_list[index-1] > value and index > 0: some_list[index] = some_list[index-1] index -= 1 # now insert value (old some_list[i]) in its proper place some_list[index] = value # now everything from 0...i is sorted def merge_sort(some_list): """ Sort the list using the merge sort algorithm. This version of merge sort returns a new list that is sorted """ # if the list <= 1 items in it, it's already sorted if len(some_list) <= 1: return some_list else: # otherwise: # - split the list in half # - call merge sort on each half # - because of recursion, each half is then sorted # - call "merge" to merge the two sorted halves into one sorted list mid_index = int(len(some_list)/2) return merge(merge_sort(some_list[:mid_index]),\ merge_sort(some_list[mid_index:])) def merge(list1, list2): """ Given two sorted list, returns a new list containing all of the items in both lists in sorted order """ result = [] index1 = 0 index2 = 0 # walkthrough each of the lists an item at a time while index1 < len(list1) and index2 < len(list2): if list1[index1] < list2[index2]: # if the item in list1 is smaller, copy it over and increment # index1 (i.e. move on to the next thing in list1) result.append(list1[index1]) index1 += 1 else: # otherwise, the item in list2 is smaller, copy it over and # increment index2 (i.e. move on to the next thing in list2) result.append(list2[index2]) index2 += 1 # copy any remaining values from the lists over # # only one of the lists should have remaining values otherwise, we wouldn't # have exited the while loop above while index1 < len(list1): result.append(list1[index1]) index1 += 1 while index2 < len(list2): result.append(list2[index2]) index2 += 1 return result def time_sort(size, sort_function): # get some random data data = list(range(size)) random.shuffle(data) start = time.time() sort_function(data) return time.time()-start def compare_sorting(): ins = [] sel = [] mer = [] sizes = list(range(5000, 10000, 500)) for size in sizes: ins.append(time_sort(size, insertion_sort)) sel.append(time_sort(size, selection_sort)) mer.append(time_sort(size, merge_sort)) #pyplot.plot(sizes, ins, sizes, sel, sizes, mer) pyplot.plot(sizes, ins, label="insertion") pyplot.plot(sizes, sel, label="selection") pyplot.plot(sizes, mer, label="merge") pyplot.xlabel("List size") pyplot.ylabel("Sorting time in seconds") pyplot.title("Timing sorting algorithms") #pyplot.legend(('insertion', 'selection', 'merge'), 'upper left') pyplot.legend() pyplot.show() def plot_merge_sort(): mer = [] increment = 5000 sizes = list(range(5000, 100000, increment)) for size in sizes: mer.append(time_sort(size, merge_sort)) # extrapolate linearly from the first two data points slope = float(mer[1]-mer[0])/(sizes[1]-sizes[0]) linear = [] linear.append(mer[0]) for i in range(1,len(mer)): linear.append(linear[i-1] + slope*increment) pyplot.plot(sizes, mer, label="merge") pyplot.plot(sizes, linear, label="linear") pyplot.xlabel("List size") pyplot.ylabel("Sorting time in seconds") pyplot.title("Merge sort vs. a line") pyplot.legend() pyplot.show()