#---------------------------------------------------------------------- # Program to test the efficiency (running time) of various methods # of sorting a list of integers. # # Copyright (C) March 6, 2020 -- Dr. William T. Verts #---------------------------------------------------------------------- import random,time,copy #---------------------------------------------------------------------- # One of the worst sorts ever. It takes no advantage of items already # in the proper order, and runs the same number of times where the list # is sorted or not. Its only benefit is that it is very short. #---------------------------------------------------------------------- def BubbleSort (L): for I in range(len(L)-1): for J in range(I+1,len(L)): if L[I] > L[J]: Temp = L[I] L[I] = L[J] L[J] = Temp return #---------------------------------------------------------------------- # Not a bad sort if the list is already sorted or nearly so, but can # as bad as BubbleSort in the worst case (list sorted in descending # order). #---------------------------------------------------------------------- def InsertionSort (L): for I in range(1,len(L)): J = I Test = L[J] while (J > 0) and (Test < L[J-1]): L[J] = L[J-1] J = J - 1 L[J] = Test return #---------------------------------------------------------------------- # Another bad sort. It, too, works OK if the list is sorted or nearly # so, but is as bad as BubbleSort in the worst case (and actually takes # longer time). #---------------------------------------------------------------------- def ExchangeSort (L): More = True N = len(L) while More: More = False N = N - 1 for I in range(N): if L[I] > L[I+1]: Temp = L[I] L[I] = L[I+1] L[I+1] = Temp More = True return #---------------------------------------------------------------------- # A very good sort and simple to write. #---------------------------------------------------------------------- def ShellsSort (L): N = len(L) M = N // 2 while (M > 0): for J in range(M,N): Test = L[J] I = J - M while (I >= 0) and (L[I] > Test): L[I+M] = L[I] I = I - M if (I+M != J): L[I+M] = Test M = M // 2 return #---------------------------------------------------------------------- # An excellent sort in general, but a few unusual cases can make # it as bad as BubbleSort. Recursive (containing a function that # calls itself). #---------------------------------------------------------------------- def QuickSort (L): def LocalSort (Low,High): if (Low >= High): return L2 = Low H2 = High Pivot = L[(L2+H2) // 2] while (L2 <= H2): while L[L2] < Pivot: L2 = L2 + 1 while L[H2] > Pivot: H2 = H2 - 1 if L2 <= H2: Temp = L[L2] L[L2] = L[H2] L[H2] = Temp L2 = L2 + 1 H2 = H2 - 1 if Low < H2: LocalSort(Low,H2) if L2 < High: LocalSort(L2,High) return LocalSort (0, len(L)-1) return #---------------------------------------------------------------------- # The built-in Python sort. Very complicated, but screamingly fast. # Worst-case performance equals QuickSort's average case, best case # (list contains a lot of sorted chunks) is MUCH faster. The # implementation of Tim's Sort (named after Tim Peters) is 3300 lines # of C code. #---------------------------------------------------------------------- def TimsSort (L): L.sort() return #---------------------------------------------------------------------- # Scramble the order of a list of numbers by picking two indexes at # random and swapping their contents, and doing this the same number of # times as there are items in the list. #---------------------------------------------------------------------- def Scramble (L): N = len(L) for I in range(N): N1 = random.randrange(N) N2 = random.randrange(N) # swap L[N1] with L[N2] Temp = L[N1] L[N1] = L[N2] L[N2] = Temp return #---------------------------------------------------------------------- # Function to check if a list is sorted. This is to verify that a # sorting technique actually worked correctly. #---------------------------------------------------------------------- def IsSorted (L): for I in range(len(L)-1): if L[I] > L[I+1]: return False return True #---------------------------------------------------------------------- # Check the performance of a particular sorting function. The first # argument is the list to sort, the second argument is the sorting # function to test, and the third argument is the name of the sorting # technique. Notice the use of formatting in the string being printed #(see page 330 of the Companion). Returns the total elapsed time. #---------------------------------------------------------------------- def Performance (L, SortFunction, SortName): NewList = copy.deepcopy(L) # Copy L... Before = time.perf_counter() SortFunction(NewList) # ...and sort the copy. After = time.perf_counter() Elapsed = After - Before while len(SortName) < 15: SortName = SortName + " " print (SortName, " = %10.7f" % Elapsed, " seconds, Sorted=", IsSorted(NewList)) return Elapsed #---------------------------------------------------------------------- # Get the number of items, build a list, and test the performance # of a number of sorting techniques. Write the results out to a # comma-separated-value (CSV) file that can be read in to Microsoft # Excel for further analysis. #---------------------------------------------------------------------- Handle = open("MyData.csv","w") Handle.write('"N","Bubble","Insertion","Exchange","Shell","Quick","Tims"\n') for N in range(1000,20001,1000): print ("------------------------------------------") print ("N=",N) L = [] # Build a list of for I in range(N): # N integers from L = L + [I] # 0 up through N-1 Scramble(L) # Scramble the order of items in the list S = '"' + str(N) + '"' S = S + ',"' + str(Performance(L, BubbleSort, "Bubble Sort")) + '"' S = S + ',"' + str(Performance(L, InsertionSort, "Insertion Sort")) + '"' S = S + ',"' + str(Performance(L, ExchangeSort, "Exchange Sort")) + '"' S = S + ',"' + str(Performance(L, ShellsSort, "Shell's Sort")) + '"' S = S + ',"' + str(Performance(L, QuickSort, "QuickSort")) + '"' S = S + ',"' + str(Performance(L, TimsSort, "Tim's Sort")) + '"' Handle.write(S + "\n") Handle.close() print ("") print ("Now go find MyData.csv and load it into Excel!")