def merge_sort(items, iteration=0, side=None): # `iteration` and `side` are used for testing purposes, # visualizing the recursive nature of the divide and conquer algorithm. _len = len(items) if _len < 2: return items pivot = _len // 2 # Keep subdividing based on pivot, # until an empty list is all that is left. left = items[:pivot] right = items[pivot:] # Print each side, keeping track of recursive count to visually # indicate how many recursive calls were made. # print (side if side else '[ROOT]'), (iteration * 2) * '.', left, right return merge( merge_sort(left, iteration=iteration + 1, side='left'), merge_sort(right, iteration=iteration + 1, side='right')) if __name__ == '__main__': with Section('Merge Sort'): results = run_sorting_trials(merge_sort) ppr(results) with Section('Merge Sort - integers'): ppr(merge_sort([rr(1, 9999) for _ in range(20)])) with Section('Merge Sort - floating point integers'): ppr(merge_sort([random() * float(rr(1, 9999)) for _ in range(20)]))
def merge_sort(items, iteration=0, side=None): # `iteration` and `side` are used for testing purposes, # visualizing the recursive nature of the divide and conquer algorithm. _len = len(items) if _len < 2: return items pivot = _len // 2 # Keep subdividing based on pivot, # until an empty list is all that is left. left = items[:pivot] right = items[pivot:] # Print each side, keeping track of recursive count to visually # indicate how many recursive calls were made. # print (side if side else '[ROOT]'), (iteration * 2) * '.', left, right return merge(merge_sort(left, iteration=iteration + 1, side='left'), merge_sort(right, iteration=iteration + 1, side='right')) if __name__ == '__main__': with Section('Merge Sort'): results = run_sorting_trials(merge_sort) ppr(results) with Section('Merge Sort - integers'): ppr(merge_sort([rr(1, 9999) for _ in range(20)])) with Section('Merge Sort - floating point integers'): ppr(merge_sort([random() * float(rr(1, 9999)) for _ in range(20)]))
def quick_sort(items, low=None, high=None): def partition(items, low, high): pivot_index = (low + high) / 2 pivot_value = items[pivot_index] items = swap_item(items, pivot_index, high) store_index = low for k in range(low, high): if items[k] < pivot_value: items = swap_item(items, k, store_index) store_index += 1 items = swap_item(items, store_index, high) return store_index num_items = len(items) if len(items) < 2: return items if low is None: low = 0 if high is None: high = num_items - 1 if low < high: partitioned = partition(items, low, high) quick_sort(items, low=low, high=partitioned - 1) quick_sort(items, low=partitioned + 1, high=high) return items if __name__ == '__main__': with Section('Quick Sort'): ppr(run_sorting_trials(quick_sort, magnitudes=[10, 100, 1000]))
last_offset = 0 # Make sure maxgaps is never greater than the number of items. while maxgaps > num_items: maxgaps -= 1 # Prevent passing in div by zero errors. if maxgaps == 0: maxgaps = 1 # Get the gap division number based on length and maxgaps. gap_sections = num_items // maxgaps if num_items < 2: return items for k in range(maxgaps): # Add the sub groups by the last_offset and the current gap # e.g. [0, 10], [10, 20], [20, 30]... sub_groups += insertion_sort( items[last_offset:last_offset + gap_sections]) # Update the last offset for the next index. last_offset += gap_sections # Return the results with the typical quick sort. return quick_sort(sub_groups) if __name__ == '__main__': with Section('Shell Sort'): TEST_MAGNITUDES = [4, 10, 50, 100, 500, 1000, 10000] # Compare helper sorting functions # in isolation to the hybrid shell function ppr(run_sorting_trials(shell_sort, magnitudes=TEST_MAGNITUDES)) ppr(run_sorting_trials(quick_sort, magnitudes=TEST_MAGNITUDES)) ppr(run_sorting_trials(insertion_sort, magnitudes=TEST_MAGNITUDES))
sys.path.append(getcwd()) from MOAL.helpers.display import Section from MOAL.helpers.trials import run_sorting_trials from pprint import pprint as ppr def bubble_sort(items): num_items = len(items) if num_items < 2: return items while num_items > 0: for k in range(num_items): try: if items[k] > items[k + 1]: copy = items[k] copy_next = items[k + 1] items[k] = copy_next items[k + 1] = copy elif items[k] == items[k + 1]: continue except IndexError: continue num_items -= 1 return items if __name__ == '__main__': with Section('Bubble Sort'): ppr(run_sorting_trials(bubble_sort, test_output=True))
# Based off of algorithm from http://en.wikipedia.org/wiki/Selection_sort def selection_sort(items): num_items = len(items) if num_items < 2: return items curr_min = 0 for j in range(num_items): # Assign minimum to j, initially curr_min = j # Loop through all elements /after/ j, # checking to find the new smallest item. for i in range(j + 1, num_items): # Update current min if this one is smaller. if items[i] < items[curr_min]: curr_min = i # After the internal loop finishes, # check (on each outer iteration) if j is less than the new curr_min. # If so, then a smaller item was found and needs to be swapped. if curr_min != j: swap_item(items, j, curr_min) return items if __name__ == '__main__': with Section('Selection Sort'): ppr(run_sorting_trials( selection_sort, magnitudes=[10, 100, 1000, 5000]))
from os import getcwd from os import sys sys.path.append(getcwd()) from MOAL.helpers.display import Section from MOAL.helpers.trials import run_sorting_trials from random import randrange as rr from pprint import pprint as ppr def bogo_sort(items): num_items = len(items) # Cheating :) correct = sorted(items) while correct != items: rand_swap_a = rr(0, num_items) rand_swap_b = rr(0, num_items) if items[rand_swap_a] > items[rand_swap_b]: copy_a = items[rand_swap_a] copy_b = items[rand_swap_b] items[rand_swap_a] = copy_b items[rand_swap_b] = copy_a print(items) return items if __name__ == "__main__": with Section("Bogo Sort (LOL)"): ppr(run_sorting_trials(bogo_sort, magnitudes=[3, 5, 10]))
from MOAL.helpers.display import Section from MOAL.helpers.display import prnt from MOAL.helpers.trials import run_sorting_trials def insertion_sort(items): if len(items) < 2: return items for k, item in enumerate(items): # Keep a copy of the item and the index # during each iteration copy = items[k] j = k while j > 0 and items[j - 1] > copy: # Swap current element with the previous one, which is lesser items[j] = items[j - 1] # Decrement and continue until j is 0, # which is the beginning of the list. j = j - 1 # Once the while loop is complete, update the original copy # index with the new index for j (which was determined # when j - 1 was no longer greater than copy.) items[j] = copy return items if __name__ == '__main__': with Section('Insertion Sort'): results = run_sorting_trials(insertion_sort) prnt('Insertion sort results:', results)
if __name__ == '__main__': from os import getcwd from os import sys sys.path.append(getcwd()) from MOAL.helpers.display import Section from MOAL.helpers.trials import run_sorting_trials from random import randrange as rr from pprint import pprint as ppr def bogo_sort(items): num_items = len(items) # Cheating :) correct = sorted(items) while correct != items: rand_swap_a = rr(0, num_items) rand_swap_b = rr(0, num_items) if items[rand_swap_a] > items[rand_swap_b]: copy_a = items[rand_swap_a] copy_b = items[rand_swap_b] items[rand_swap_a] = copy_b items[rand_swap_b] = copy_a print(items) return items if __name__ == '__main__': with Section('Bogo Sort (LOL)'): ppr(run_sorting_trials(bogo_sort, magnitudes=[3, 5, 10]))
def partition(items, low, high): pivot_index = (low + high) / 2 pivot_value = items[pivot_index] items = swap_item(items, pivot_index, high) store_index = low for k in range(low, high): if items[k] < pivot_value: items = swap_item(items, k, store_index) store_index += 1 items = swap_item(items, store_index, high) return store_index num_items = len(items) if len(items) < 2: return items if low is None: low = 0 if high is None: high = num_items - 1 if low < high: partitioned = partition(items, low, high) quick_sort(items, low=low, high=partitioned - 1) quick_sort(items, low=partitioned + 1, high=high) return items if __name__ == '__main__': with Section('Quick Sort'): ppr(run_sorting_trials(quick_sort, magnitudes=[10, 100, 1000]))