[Algorithm] Sorting 排序
Bubble Sort 泡沫排序 T: O(n ^ 2), S: O(1)
依序把最大的放到最後(如泡沫慢慢浮上水面)
- [2, 3, 5, 4, 1]
- [2, 3, 4, 1, 5]
- [2, 3, 1, 4, 5]
- [2, 1, 3, 4, 5]
- [1, 2, 3, 4, 5]
def bubble_sort (arr):
  for i in range(len(arr)):
    for j in range(len(arr) - i - 1):
      if arr[j] > arr[j + 1]:
        arr[j], arr[j + 1] = arr[j + 1], arr[j]
Insertion Sort 插入排序 T: O(n ^ 2), S: O(1)
- [2, 3, 5, 4, 1] ≡ 2 → [] = [2]
- [2, 3, 5, 4, 1]≡ 3 → [2] = [2, 3]
- [2, 3, 5, 4, 1]≡ 5 → [2, 3] = [2, 3, 5]
- [2, 3, 5, 4, 1]≡ 4 → [2, 3, 5] = [2, 3, 4, 5]
- [2, 3, 5, 5, 1]
- [2, 3, 4, 5, 1]
 
- [2, 3, 4, 5, 1]≡ 1 → [2, 3, 4, 5] = [1, 2, 3, 4, 5]
- [2, 3, 4, 5, 5]
- [2, 3, 4, 4, 5]
- [2, 3, 3, 4, 5]
- [2, 2, 3, 4, 5]
- [1, 2, 3, 4, 5]
 
def insertion_sort(arr):
  for i in range(len(arr)):
    key = arr[i]
    j = i - 1
    while j > 0 and arr[j] > key:
      arr[j + 1] = arr[j]
      j -= 1
    arr[j + 1] = key
Shell Sort 希爾排序
選擇 Gap sequences 為 (5, 3, 1) 為例
- [13, 14, 94, 33, 82, 25, 59, 94, 65, 23, 45, 27, 73, 25, 39, 10]
- 5 – Sorting:
- [[13, 14, 94, 33, 82], 
 [25, 59, 94, 65, 23],
 [45, 27, 73, 25, 39],
 [10]]
- 分別對每行進行插入排序
 [[10, 14, 73, 25, 23],
 [13, 27, 94, 33, 39],
 [25, 59, 94, 65, 82],
 [45]]
 
- [[13, 14, 94, 33, 82], 
- 還原為一列:
 [10, 14, 73, 25, 23, 13, 27, 94, 33, 39, 25, 59, 94, 65, 82, 45]
- 3 – Sorting
- [[10, 14, 73], 
 [25, 23, 13],
 [27, 94, 33],
 [39, 25, 59],
 [94, 65, 82],
 [45]]
- [[10, 14, 13], 
 [25, 23, 33],
 [27, 25, 59],
 [39, 65, 73],
 [45, 94, 82],
 [94]]
 
- [[10, 14, 73], 
- 還原為一列:
 [10, 14, 13, 25, 23, 33, 27, 25, 59 ,39, 65, 73, 45, 94, 82, 94]
- 1 – Sorting(會比原始資料更容易做插入排序):
 [10, 13, 14, 23, 25, 25, 27, 33, 39, 45, 59, 65, 73, 82, 94, 94]
Gap sequences 步長序列
| General term (k ≥ 1) | Concrete gaps | Worst-case Time Complexity | 
| $$ \frac{n}{2^k} $$ | $$ \frac{n}{2}, \frac{n}{4}, …, 1 $$ | $$ \Theta(n^2) $$ | 
| $$ 2^k – 1 $$ | $$ 1, 3, 7, 15, 31, 63, … $$ | $$ \Theta(n^\frac{3}{2}) $$ | 
| $$ 2^p  3^q $$ (3-smooth number) | $$ 1, 2, 3, 4, 6, 8, 9, 12, … $$ | $$ \Theta(n \log^2{n}) $$ | 
Selection Sort 選擇排序 T: O(n ^ 2), S: O(n)
- [2, 3, 5, 4, 1] → [1, 3, 5, 4, 2]
- [1, 3, 5, 4, 2] → [1, 2, 5, 4, 3]
- [1, 2, 5, 4, 3] → [1, 2, 3, 4, 5]
- [1, 2, 3, 4, 5]
- [1, 2, 3, 4, 5]
def selection_sort(arr):
  for i in range(len(arr) - 1):
    min_i = i
    for j in range(i + 1, range(len(arr)):
      if arr[j] < arr[min_i]:
        min_i = j
    if min_i != i:
      arr[i], arr[min_i] = arr[min_i], arr[i]
Quick Sort 快速排序 T: O(n * log(n)) ~ O(n ^ 2)
使用二分法 (binary method / divide and conquer)
- [5, 9, 6, 1, 3, 8, 4, 7, 2] → pivot: 5
 → less: [1, 3, 4, 2], greater: [9, 6, 8, 7]
 → quick_sort([1, 3, 4, 2]) + [5] + quick_sort([9, 6, 8, 7])
- → (quick_sort([]) +[1] + quick_sort([3, 4, 2])) + [5] + (quick_sort([6, 8, 7]) + [9]+ quick_sort([]))
- → ([1] + (quick_sort([2]) + [3] + quick_sort([4]))) + [5] + ((quick_sort([]) +[6] + quick_sort([8, 7])) + [9])
- → ([1] + (([2]) + [3] + ([4]))) + [5] + (([6] + (quick_sort([]) +[7] + quick_sort([8])) + [9])
- → ([1] + (([2]) + [3] + ([4]))) + [5] + (([6] + ([7] + [8])) + [9])
- → [1, 2, 3, 4, 5, 6, 7, 8, 9]
Time Complexity: 
 Average Case: O(n * log(n))
Average Case: O(n * log(n))
 Worst Case: O(n ^ 2)
Worst Case: O(n ^ 2)
Space Complexity: Ω(n)
def quick_sort (arr):
  if len(arr) <= 1: return array
  pivot = arr[0] # select a pivot
  less, greater = [], []
  for n in arr[1:]:
    if n <pivot:
      less.append(n)
    else:
      greater.append(n)
  return quick_sort(less) + [pivot] + quick_sort(greater)
In-plase Version, S: O(1)
- [5, 9, 6, 1, 4, 7, 3, 8, 2]
- [5, 9, 6, 1, 4, 7, 3, 8, 2]
- [5, 9, 6, 1, 4, 7, 3, 8, 2]
- [5, 1, 6, 9, 4, 7, 3, 8, 2]
- [5, 1, 4, 9, 6, 7, 3, 8, 2]
- [5, 1, 4, 9, 6, 7, 3, 8, 2]
- [5, 1, 4, 3, 6, 7, 9, 8, 2]
- [5, 1, 4, 3, 6, 7, 9, 8, 2]
- [5, 1, 4, 3, 2, 7, 9, 8, 6]
Time Complexity: 
 Average Case: O(n * log(n))
Average Case: O(n * log(n))
 Worst Case: O(n ^ 2)
Worst Case: O(n ^ 2)
Space Complexity: O(1)
def quick_sort (arr):
  if len(arr) <= 1: return array
  pivot = arr[0] # select a pivot
  greater_start = 1
  for i, n in enumerate(array[1:]):
    if n < pivot:
      arr[i], arr[greater_start] = arr[greater_start], arr[i]
      greater_start += 1
  return quick_sort(arr[1:greater_start]) + [pivot] + quick_sort(arr[greater_start:])
Merge Sort 合併排序 T: Θ(n * log(n)), S: Θ(n)
| 2 | 3 | 5 | 4 | 1 | ||||
| ↙︎ | ↘︎ | |||||||
| 2 | 3 | 5 | 4 | 1 | ||||
| ↙︎ | ↘︎ | ↙︎ | ↘︎ | |||||
| 2 | 3 | 5 | 4 | 1 | ||||
| ↙︎ | ↘︎ | ↓ | ↓ | ↓ | ||||
| 2 | 3 | 5 | 4 | 1 | ||||
| ↘︎ | ↙︎ | ↓ | ↘︎ | ↙︎ | ||||
| 2 | 3 | 5 | 1 | 4 | ||||
| ↘︎ | ↙︎ | ↓ | ||||||
| 2 | 3 | 5 | 1 | 4 | ||||
| ↘︎ | ↙︎ | |||||||
| 1 | 2 | 3 | 4 | 5 | 
def merge_sort(array):
  if len(array) < 2: return array
  mid = (len(array) + 1) // 2
  left  = merge_sort(array[:mid])
  right = merge_sort(array[mid:])
  ret = []
  i = j = 0
  while i < len(left) or j < len(right):
    if i == len(left) or \
         (i < len(left) and j < len(right) and left[i] > right[j]):
      ret.append(right[j])
      j += 1
    else:
      ret.append(left[i])
      i += 1
  return ret
相關例題
Heap Sort
參照 Heap 堆積
Last Updated on 2024/06/10 by A1go
 
	
           
  