def bucket_sort(numbers, num_buckets=10): """Sort given numbers by distributing into buckets representing subranges, then sorting each bucket and concatenating all buckets in sorted order. TODO: Running time: ??? Why and under what conditions? TODO: Memory usage: ??? Why and under what conditions?""" # TODO: Find range of given numbers (minimum and maximum values) minimum, maximum = find_range(numbers) # TODO: Create list of buckets to store numbers in subranges of input range buckets = [] for i in range(num_buckets): buckets.append([]) # TODO: Loop over given numbers and place each item in appropriate bucket for num in numbers: insert_index, remainder = divmod(num, len(numbers) // num_buckets) if remainder > 0: buckets[insert_index].append(num) else: buckets[insert_index - 1].append(num) # TODO: Sort each bucket using any sorting algorithm (recursive or another) for bucket in buckets: if len(bucket): bubble_sort(bucket) # TODO: Loop over buckets and append each bucket's numbers into output list input_index = 0 for bucket in buckets: for num in bucket: numbers[input_index] = num input_index += 1
def split_sort_merge(items): """Sort given items by splitting list into two approximately equal halves, sorting each with an iterative sorting algorithm, and merging results into a list in sorted order.""" mid = int(len(items) / 2) items1 = items[:mid] items2 = items[mid:] new_list = merge(bubble_sort(items1), bubble_sort(items2), []) return new_list
def _merge_sort_helper(items): if items is None: return [] if len(items) <= 3: bubble_sort(items) return items center = len(items) // 2 items1 = items[:center] items2 = items[center:] return merge(_merge_sort_helper(items1), _merge_sort_helper(items2))
def split_sort_merge(items): """Sort given items by splitting list into two approximately equal halves, sorting each with an iterative sorting algorithm, and merging results into a list in sorted order. TODO: Running time: ??? Why and under what conditions? TODO: Memory usage: ??? Why and under what conditions?""" mid = len(items) // 2 items1 = items[:mid] items2 = items[mid:] bubble_sort(items1) bubble_sort(items2) items[:] = merge(items1, items2)
def split_sort_merge(items): """Sort given items by splitting list into two approximately equal halves, sorting each with an iterative sorting algorithm, and merging results into a list in sorted order. TODO: Running time: ??? Why and under what conditions? TODO: Memory usage: ??? Why and under what conditions?""" # TODO: Split items list into approximately equal halves items1 = items[:len(items) // 2] items2 = items[len(items) // 2:] # TODO: Sort each half using any other sorting algorithm bubble_sort(items1) bubble_sort(items2) # TODO: Merge sorted halves into one list in sorted order items[:] = merge(items1, items2)
def merge_sort(items): """Sort given items by splitting list into two approximately equal halves, sorting each recursively, and merging results into a list in sorted order. TODO: Running time: ??? Why and under what conditions? TODO: Memory usage: ??? Why and under what conditions?""" if len(items) <= 3: bubble_sort(items) else: middle_index = len(items) // 2 right_half = items[middle_index:] merge_sort(right_half) left_half = items[:middle_index] merge_sort(left_half) for index, item in enumerate(merge(right_half, left_half)): items[index] = item
def split_sort_merge(items): """Sort given items by splitting list into two approximately equal halves, sorting each with an iterative sorting algorithm, and merging results into a list in sorted order. Running time: O((n/2)^2) -> O(n^2) When the left and right halves are in reverse order Memory usage: O(n) New memory is created to store new ordered list""" # Split items list into approximately equal halves middle = len(items) // 2 left = items[:middle] right = items[middle:] # Sort each half using any other sorting algorithm insertion_sort(left) # O(n^2) bubble_sort(right) # O(n^2) # Merge sorted halves into one list in sorted order # Overwrite content of original list with content of sorted list items[:] = merge(left, right)
def test_bubble_sort_on_sorted_integers(self): # Positive test cases (examples) with lists of sorted integers assert(bubble_sort([])) == [] # Empty lists are vacuously sorted assert bubble_sort([3]) == [3] # Single item is trivially sorted assert bubble_sort([3, 3]) == [3, 3] # Duplicate items are in order assert bubble_sort([3, 5]) == [3, 5] assert bubble_sort([3, 5, 7]) == [3, 5, 7] # new added test cases sample_1 = [3, 7, 9, 11, 13, 15, 16, 17, 19, 20] assert bubble_sort(sample_1) == sample_1 sample_2 = [1, 2, 4, 5, 7, 8, 10, 15, 25, 25, 32, 37, 37, 38, 38, 39, 39, 42, 42, 47] assert bubble_sort(sample_2) == sample_2 sample_3 = [6, 9, 13, 13, 16, 17, 21, 22, 22, 22, 23, 24, 25, 29, 30, 34, 34, 36, 40, 43] assert bubble_sort(sample_3) == sample_3
def split_sort_merge(items): """ Sort given items by splitting list into two approximately equal halves, sorting each with an iterative sorting algorithm, and merging results into a list in sorted order. where: N = length of the original list, n = length of the first half, m = length second half. Also n and m is approximately(almost) equal length. so n + m approximately 2n or 2m which is, 2n = N or 2m = N Running time: O(n^2) + O(m^2) = O(2n^2) using the properties above, overall O(N^2) running time Memory usage: O(N), because when we are merging two sorted list at the end we are creating new empty list with the same length of the original list. Args: items(list): unsorted list of elements Returns: merged_list(list): sorted list of elements of original list. Reference of the original list didnt change. """ # splitting part mid = len(items) // 2 # copy the first half of the array items_1 = items[:mid] # O(n) # copy the second half of the array items_2 = items[mid:] # O(m) # sorting the splitted lists using iterative algorithms bubble_sort(items_1) # O(n^2) refer to the bubble sort docstring insertion_sort(items_2) # O(m^2) refer to insertion sort docstring # now merge two sorted arrays merged_list = merge(items_1, items_2) # O(n+m) = O(N) # to make sorting in place items[:] = merged_list
def split_sort_merge(items): """Sort given items by splitting list into two approximately equal halves, sorting each with an iterative sorting algorithm, and merging results into a list in sorted order. TODO: Running time: ??? Why and under what conditions? TODO: Memory usage: ??? Why and under what conditions?""" # Split items list into approximately equal halves median = len(items) // 2 # Using floor to give us equal halves # Calculating both left and right half left_half = items[:median + 1] right_half = items[median + 1:] # Conducting iterative sorting algo bubble sort on both halfs ... # TODO: Sort each half using any other sorting algorithm bubble_sort(left_half) bubble_sort(right_half) # Then merging the two sorted halfs using the merge func # TODO: Merge sorted halves into one list in sorted order merged_result = merge(left_half, right_half) # Copy result into input list with slice assignment items[:] = merged_result
def split_sort_merge(items): """Sort given items by splitting list into two approximately equal halves, sorting each with an iterative sorting algorithm, and merging results into a list in sorted order. Running Time: O(n^2) because of using bubble_sort and insertion_sort Memory Usage: O(n) where n is the amount of items you are merging together""" middle = len(items) // 2 left = bubble_sort(items[:middle]) # Sorting the items on the left right = insertion_sort(items[middle:]) # Sorting the items on the right sorted_items = merge(left, right) # Sets the sorted items in the list for index in range(len(items)): items[index] = sorted_items[index] return items
def test_bubble_sort_on_unsorted_integers(self): # Negative test cases (counterexamples) with lists of unsorted integers sample_1 = [5, 3] assert bubble_sort(sample_1) == sorted(sample_1) sample_2 = [3, 5, 3] assert bubble_sort(sample_2) == sorted(sample_2) sample_3 = [7, 5, 3] assert bubble_sort(sample_3) == sorted(sample_3) sample_4 = [37, 3, 5, 6, 41, 50, 17, 5, 18, 17] # new test cases assert bubble_sort(sample_4) == sorted(sample_4) sample_5 = [21, 12, 19, 5, 30, 17, 22, 22, 15, 4] assert bubble_sort(sample_5) == sorted(sample_5) sample_6 = [21, 23, 19, 16, 31, 27, 18, 6, 43, 41, 43, 12, 32, 38, 35] assert bubble_sort(sample_6) == sorted(sample_6)
def test_bubble_sort(self): for _ in range(100): random_and_sorted = _generate_testcase() SortIter.bubble_sort(random_and_sorted[0]) assert random_and_sorted[0] == random_and_sorted[1]
else: # Don't explode, just warn user and show list of sorting functions print('Sorting function {!r} does not exist'.format(sort_name)) print('Available sorting functions:') for name in globals(): if 'sort' in name: print(' {}'.format(name)) return # Get num_items and max_value, but don't explode if input is not an integer try: num_items = int(args[1]) if len(args) >= 2 else 20 max_value = int(args[2]) if len(args) >= 3 else 50 # print('Num items: {}, max value: {}'.format(num_items, max_value)) except ValueError: print('Integer required for `num` and `max` command-line arguments') return # Test sort function test_sorting(sort_function, num_items, max_value) if __name__ == '__main__': # main() # nums = [1,3,9,7,4] nums = [1239, 212, 1, 31, 492, 12321, 1323, 8, 12] nums2 = [1, 2, 3, 4, 5] # print(is_sorted(nums)) # print(is_sorted(nums2)) print(bubble_sort(nums))