Personal blog written from scratch using Node.js, Bootstrap, and MySQL. https://jrtechs.net
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

211 lines
5.8 KiB

  1. # Insertion Sort
  2. Selection sort although not very efficient is often used when the arrays you are sorting are very small.
  3. Another benefit of insertion sort is that it is very easy to program.
  4. Essentially, this algorithm has a sorted section which slowly grows as it pull in new elements to their sorted position.
  5. ## Functional Notation
  6. $$
  7. s([]) = []\\
  8. s(x::xs) = i(x, s(xs))
  9. $$
  10. $$
  11. i(x, []) = [x]\\
  12. i(x,y::ys) = x::y::ys, if x \leq y\\
  13. i(x,y::yx) = y::i(x, ys) otherwise
  14. $$
  15. If you are not familiar with functional programming, this way of writing insertion sort may scare you.
  16. Essentially the 's' stands for sort and the 'i' stands for insert.
  17. For the sort section you are taking off the first element and inserting it into the rest of the sorted array.
  18. For the insert section you are placing the element in its sorted position.
  19. ## Imperative Notation
  20. ```Python
  21. def insertionSort(alist):
  22. for index in range(1,len(alist)):
  23. currentvalue = alist[index]
  24. position = index
  25. while position > 0 and alist[position-1] > currentvalue:
  26. alist[position] = alist[position-1]
  27. position = position-1
  28. alist[position] = currentvalue
  29. return alist
  30. ```
  31. This notation will make python programmers feel a lot more comfortable.
  32. # Merge Sort
  33. Merge sort is a classic example of a divide and conquer algorithm.
  34. Each iteration, the problem is cut in half making sorting it easier.
  35. Once you have your array divided into sorted sections, it is easy to combine into a larger sorted array.
  36. ## Functional Notation
  37. $$
  38. d([]) = ([],[])\\
  39. d([x]) = ([x],[])\\
  40. d(x_1::x_2::xs) = let (b_1, b_2) = d(xs) in (x_1::b_1, x_2::b_2)\\
  41. $$
  42. $$
  43. mSort([]) = []\\
  44. mSort([x]) = [x]\\
  45. mSort(xs) = let(b_1, b_2) = d(xs) in mSort(b_1) combine mSort(b_2)\\
  46. $$
  47. ## Python Implementation
  48. ```Python
  49. def merge_sort(a):
  50. if len(a) < 2:
  51. return a
  52. l = a[0:len(a)//2]
  53. r = a[len(a)//2:]
  54. return merge(merge_sort(l), merge_sort(r))
  55. def merge(a, b):
  56. out = []
  57. i = 0
  58. j = 0
  59. while i < len(a) or j < len(b):
  60. if i >= len(a):
  61. out.append(b[j])
  62. j += 1
  63. elif j >= len(b):
  64. out.append(a[i])
  65. i += 1
  66. else:
  67. if a[i] <= b[j]:
  68. out.append(a[i])
  69. i += 1
  70. else:
  71. out.append(b[j])
  72. j += 1
  73. return out
  74. ```
  75. # Quick Sort
  76. This sorting algorithm asymptotically is the same as merge sort: $O(nlog(n))$.
  77. However, in practice this algorithm is actually faster than merge sort due to constant factors.
  78. The general premise of this algorithm is that each iteration you will divide your array into three sections : less, equal, greater.
  79. The items in each section are based on a random element in the array.
  80. You will continue this process until you get every element by itself which makes it trivial to sort.
  81. ## Functional Notation
  82. $$
  83. qSort([]) = []\\
  84. qSort(x::xs) = qSort([y \in xs | y < x]) + [y \in x:xs | y = x] + qSort([y \in xs | y > x])\\
  85. $$
  86. This functional notation heavily uses the notion of array comprehensions.
  87. ## Memory Greedy Solution
  88. ```
  89. def quickSortNormal(data):
  90. """
  91. This is the traditional implementation of quick sort
  92. where there are two recursive calls.
  93. """
  94. if len(data) == 0:
  95. return []
  96. else:
  97. less, equal, greater = partition(data)
  98. return quickSortNormal(less) + equal + quickSortNormal(greater)
  99. ```
  100. ## Accumulation Solution
  101. ```
  102. def quick_sort_accumulation(data, a):
  103. """
  104. Implementation of quickSort which forces tail recursion
  105. by wrapping the second recursive in the tail positioned
  106. recursive call and added an accumulation variable.
  107. """
  108. if len(data) == 0:
  109. return a
  110. less, equal, greater = partition(data)
  111. return quick_sort_accumulation(less,
  112. equal + quick_sort_accumulation(greater, a))
  113. def quicksort(data):
  114. """
  115. Wrapper function for quick sort accumulation.
  116. """
  117. return quick_sort_accumulation(data, [])
  118. ```
  119. ## In-Place Sorting Implementation
  120. ```
  121. def iterative_partition(data, left, right):
  122. """
  123. Function which partitions the data into two segments,
  124. the left which is less than the pivot and the right
  125. which is greater than the pivot. The pivot for this
  126. algo is the right most index. This function returns
  127. the ending index of the pivot.
  128. :param data: array to be sorted
  129. :param left: left most portion of array to look at
  130. :param right: right most portion of the array to look at
  131. """
  132. x = data[right]
  133. i = left - 1
  134. j = left
  135. while j < right:
  136. if data[j] <= x:
  137. i = i + 1
  138. data[i], data[j] = data[j], data[i]
  139. j = j+1
  140. data[i + 1], data[right] = data[right], data[i + 1]
  141. return i + 1
  142. def iterative_quick_sort(data):
  143. """
  144. In place implementation of quick sort
  145. Wrapper function for iterative_quick_sort_helper which
  146. initializes, left, right to be the extrema of the array.
  147. """
  148. iterative_quick_sort_helper(data, 0, len(data) -1)
  149. return data
  150. def iterative_quick_sort_helper(data, left, right):
  151. """
  152. Uses the divide and conquer algo to sort an array
  153. :param data: array of data
  154. :param left: left index bound for sorting
  155. :param right: right bound for sorting
  156. """
  157. if left < right:
  158. pivot = iterative_partition(data, left, right)
  159. iterative_quick_sort_helper(data, left, pivot -1)
  160. iterative_quick_sort_helper(data, pivot+1, right)
  161. ```
  162. # Time Complexities Overview
  163. | Algorithm &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Worst &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Average &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Best &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |
  164. |--- |:--- |:--- |:--- |
  165. | Insertion | $0(n^2)$ | $0(n^2)$ | $0(n^2)$ |
  166. | Merge | $0(nlog(n))$ | $0(nlog(n))$ | $0(nlog(n))$ |
  167. | Quick | $0(nlog(n))$ | $0(nlog(n))$ | $0(n^2)$ |