""" 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 :param some_list: (list) list to sort :return: (None) """ # 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 :param some_list: (list) list to sort :return: (None) """ for i in range(0, len(some_list)): # everything from 0...i is sorted already j = i while j > 0 and some_list[j] < some_list[j-1]: (some_list[j], some_list[j - 1]) = \ (some_list[j - 1], some_list[j]) j = j - 1 # an alternative implementation with two nested for loops # for i in range(0, len(some_list)): # # everything from 0...i is sorted already # for j in range(i, 0, -1): # if some_list[j] < some_list[j-1]: # (some_list[j], some_list[j-1]) = \ # (some_list[j-1], some_list[j]) # else: # break 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(): sorting_algorithms = [insertion_sort, selection_sort, merge_sort] names = ["insertion", "selection", "merge"] times = [[], [], []] sizes = list(range(5000, 10000, 500)) for size in sizes: for i in range(len(sorting_algorithms)): times[i].append(time_sort(size, sorting_algorithms[i])) # pyplot.plot(sizes, ins, sizes, sel, sizes, mer) for i in range(len(sorting_algorithms)): pyplot.plot(sizes, times[i], label=names[i]) 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()