Advertisement
Guest User

Untitled

a guest
Jan 29th, 2020
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.92 KB | None | 0 0
  1. from time import sleep
  2. import visualizer as vs
  3.  
  4. test = False
  5.  
  6.  
  7. class Array:
  8.  
  9. full_array = None
  10.  
  11. def plot(self):
  12. if not test:
  13. vs.plot(Array.full_array)
  14.  
  15. def set_all(self, values):
  16. for i in range(len(self.values)):
  17. self.values[i] = values[i]
  18. for i in range(len(self.values)):
  19. Array.full_array[self.lower_index + i] = values[i]
  20. self.plot()
  21.  
  22. def __init__(self, values, lower_index=0):
  23. self.lower_index = lower_index
  24. self.values = list(values)
  25.  
  26. if Array.full_array == None:
  27. Array.full_array = list(values)
  28. self.plot()
  29.  
  30. def swap(self, index1, index2):
  31. self.values[index2], self.values[index1] = self.values[index1], self.values[index2]
  32. Array.full_array[self.lower_index + index2], Array.full_array[self.lower_index +
  33. index1] = Array.full_array[self.lower_index + index1], Array.full_array[self.lower_index + index2]
  34. self.plot()
  35.  
  36. def set(self, index, num):
  37. self.values[index] = num
  38. Array.full_array[self.lower_index + index] = num
  39. self.plot()
  40.  
  41. def get_len(self):
  42. return len(self.values)
  43.  
  44.  
  45. def bubble_sort(nums): # n^2
  46. # We set swapped to True so the loop looks runs at least once
  47. swapped = True
  48. while swapped:
  49. swapped = False
  50. for i in range(nums.get_len() - 1):
  51. if nums.values[i] > nums.values[i + 1]:
  52. # Swap the elements
  53. nums.swap(i, i + 1)
  54. # Set the flag to True so we'll loop again
  55. swapped = True
  56.  
  57. #Modified version of Insertion Sort
  58. def shell_sort(nums): # Average : O(n^1.5)
  59.  
  60. n = nums.get_len()
  61. #This gap represents the length of gap in each iteration, starting with n/2 and then reducing it in each iteration.
  62. gap = n//2
  63.  
  64. # Start with insertion sort for gap size of 'gap'. Elements in nums[0...gap-1] are already in the order of gapped elements.
  65. # So, keep adding one more element until the entire array is gap sorted.
  66. while gap > 0:
  67. #Since elements from nums[0...gap-1] are already in required order, do it for nums[gap...n-1]
  68. for i in range(gap, n):
  69.  
  70. # Make nums[i] as temp in order to make a hole at position i
  71. temp = nums.values[i]
  72.  
  73. #variable to store the correct or final position of nums[i]
  74. correctIndex = i
  75. # Shift earlier gap-sorted elements till we find the correct position for nums[i]
  76. while correctIndex >= gap and nums.values[correctIndex-gap] > temp:
  77. nums.set(correctIndex, nums.values[correctIndex-gap])
  78. correctIndex -= gap
  79.  
  80. # Set nums[i], which was stored in temp at its correct position
  81. nums.set(correctIndex, temp)
  82. gap //= 2
  83.  
  84.  
  85. #Modified version of Bubble Sort
  86. def comb_sort(nums): #Best : O(nlogn) , Worst : O(n^2)
  87. n = nums.get_len()
  88. # This gap represents the length of gap in each iteration, starting with n and then reducing it in each iteration.
  89. gap = n
  90. # Initialize swapped as true to make sure that loop runs
  91. swapped = True
  92. #Iterate till either gap is reduced to 1 or till when swapping is no more done
  93. while gap !=1 or swapped == 1:
  94. # next value of gap
  95. gap = (gap * 10)//13
  96. if gap<1:
  97. gap = 1
  98. # Mark swapped as false to know whether swapped has happened or not
  99. swapped = False
  100. # Compare all elements with current gap
  101. for index in range(0, n-gap):
  102. if nums.values[gap + index] < nums.values[index]:
  103. nums.swap(index, gap + index)
  104. swapped = True
  105.  
  106.  
  107.  
  108. def selection_sort(nums): # n^2
  109. # This value of i corresponds to how many values were sorted
  110. for i in range(nums.get_len()):
  111. # We assume that the first item of the unsorted segment is the smallest
  112. lowest_value_index = i
  113. # This loop iterates over the unsorted items
  114. for j in range(i + 1, nums.get_len()):
  115. if nums.values[j] < nums.values[lowest_value_index]:
  116. lowest_value_index = j
  117. # Swap values of the lowest unsorted element with the first unsorted
  118. # element
  119. nums.swap(i, lowest_value_index)
  120.  
  121.  
  122. def insertion_sort(nums): # n^2
  123. # Start on the second element as we assume the first element is sorted
  124. for i in range(1, nums.get_len()):
  125. item_to_insert = nums.values[i]
  126. # And keep a reference of the index of the previous element
  127. j = i - 1
  128. # Move all items of the sorted segment forward if they are larger than
  129. # the item to insert
  130. while j >= 0 and nums.values[j] > item_to_insert:
  131. nums.set(j + 1, nums.values[j])
  132. j -= 1
  133. # Insert the item
  134. nums.set(j + 1, item_to_insert)
  135.  
  136.  
  137. def heap_sort(nums): # n * logn
  138.  
  139. def heapify(nums, heap_size, root_index):
  140. # Assume the index of the largest element is the root index
  141. largest = root_index
  142. left_child = (2 * root_index) + 1
  143. right_child = (2 * root_index) + 2
  144.  
  145. # If the left child of the root is a valid index, and the element is greater
  146. # than the current largest element, then update the largest element
  147. if left_child < heap_size and nums.values[left_child] > nums.values[largest]:
  148. largest = left_child
  149.  
  150. # Do the same for the right child of the root
  151. if right_child < heap_size and nums.values[right_child] > nums.values[largest]:
  152. largest = right_child
  153.  
  154. # If the largest element is no longer the root element, swap them
  155. if largest != root_index:
  156. nums.swap(root_index, largest)
  157. # Heapify the new root element to ensure it's the largest
  158. heapify(nums, heap_size, largest)
  159.  
  160. n = nums.get_len()
  161.  
  162. # Create a Max Heap from the list
  163. # The 2nd argument of range means we stop at the element before -1 i.e.
  164. # the first element of the list.
  165. # The 3rd argument of range means we iterate backwards, reducing the count
  166. # of i by 1
  167. for i in range(n, -1, -1):
  168. heapify(nums, n, i)
  169.  
  170. # Move the root of the max heap to the end of
  171. for i in range(n - 1, 0, -1):
  172. nums.swap(i, 0)
  173. heapify(nums, i, 0)
  174.  
  175.  
  176. def merge_sort(nums, lower_index=0): # n * logn
  177. def merge(left_list, right_list):
  178. sorted_list = []
  179. left_list_index = right_list_index = 0
  180.  
  181. # We use the list lengths often, so it's handy to make variables
  182. left_list_length, right_list_length = len(left_list), len(right_list)
  183.  
  184. for _ in range(left_list_length + right_list_length):
  185. if left_list_index < left_list_length and right_list_index < right_list_length:
  186. # We check which value from the start of each list is smaller
  187. # If the item at the beginning of the left list is smaller, add it
  188. # to the sorted list
  189. if left_list[left_list_index] <= right_list[right_list_index]:
  190. sorted_list.append(left_list[left_list_index])
  191. left_list_index += 1
  192. # If the item at the beginning of the right list is smaller, add it
  193. # to the sorted list
  194. else:
  195. sorted_list.append(right_list[right_list_index])
  196. right_list_index += 1
  197.  
  198. # If we've reached the end of the of the left list, add the elements
  199. # from the right list
  200. elif left_list_index == left_list_length:
  201. sorted_list.append(right_list[right_list_index])
  202. right_list_index += 1
  203. # If we've reached the end of the of the right list, add the elements
  204. # from the left list
  205. elif right_list_index == right_list_length:
  206. sorted_list.append(left_list[left_list_index])
  207. left_list_index += 1
  208.  
  209. return sorted_list
  210.  
  211. # If the list is a single element, return it
  212. if nums.get_len() <= 1:
  213. return nums.values
  214.  
  215. # Use floor division to get midpoint, indices must be integers
  216. mid = nums.get_len() // 2
  217.  
  218. # Sort and merge each half
  219. left_list = merge_sort(Array(nums.values[:mid], lower_index))
  220. right_list = merge_sort(Array(nums.values[mid:], mid), mid)
  221.  
  222. nums.set_all(left_list + right_list)
  223.  
  224. # Merge the sorted lists into a new one
  225. sorted_list = merge(left_list, right_list)
  226.  
  227. nums.set_all(sorted_list)
  228. return sorted_list
  229.  
  230.  
  231. def quick_sort(nums): # n^2
  232. def partition(nums, low, high):
  233. # We select the middle element to be the pivot. Some implementations select
  234. # the first element or the last element. Sometimes the median value becomes
  235. # the pivot, or a random one. There are many more strategies that can be
  236. # chosen or created.
  237. pivot = nums.values[(low + high) // 2]
  238. i = low - 1
  239. j = high + 1
  240. while True:
  241. i += 1
  242. while nums.values[i] < pivot:
  243. i += 1
  244.  
  245. j -= 1
  246. while nums.values[j] > pivot:
  247. j -= 1
  248.  
  249. if i >= j:
  250. return j
  251.  
  252. # If an element at i (on the left of the pivot) is larger than the
  253. # element at j (on right right of the pivot), then swap them
  254. nums.swap(j, i)
  255.  
  256. # Create a helper function that will be called recursively
  257. def _quick_sort(items, low, high):
  258. if low < high:
  259. # This is the index after the pivot, where our lists are split
  260. split_index = partition(items, low, high)
  261. _quick_sort(items, low, split_index)
  262. _quick_sort(items, split_index + 1, high)
  263.  
  264. _quick_sort(nums, 0, nums.get_len() - 1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement