可视化排序 https://visualgo.net/en/sorting
冒泡排序(Bubble Sort) 依次两两比较,发现顺序不对则交换,重复这一过程
由于是从前向后遍历,所以第一次遍历会将最大的交换至最后一个位置,依次类推
我们记录每次遍历时最后一次交换的位置,避免后续多余的判断
稳定排序算法 时间复杂度:O(n^2) 空间复杂度:O(1) 1 2 3 4 5 6 7 8 9 def bubble_sort (arr ): last_sort, swap_count = len (arr), 0 while last_sort > 1 : last_sort, end = 1 , last_sort for i in range (1 , end): if arr[i - 1 ] > arr[i]: arr[i - 1 ], arr[i] = arr[i], arr[i - 1 ] last_sort = i swap_count += 1
选择排序(Selection Sort) 每次选择最小值放到前面
不稳定排序算法 复杂度:O(n^2) 空间复杂度:O(1) 1 2 3 4 5 6 7 8 9 10 def selection_sort (arr ): swap_count = 0 for i in range (len (arr)): min_idx = i for j in range (i + 1 , len (arr)): if arr[j] < arr[min_idx]: min_idx = j if min_idx != i: swap_count += 1 arr[i], arr[min_idx] = arr[min_idx], arr[i]
插入排序(Insertion Sort) 依次选择元素,插入到前面已排序的位置
稳定排序算法 复杂度:O(n^2) 空间复杂度:O(1) 1 2 3 4 5 6 7 8 9 def insertion_sort (arr ): swap_count = 0 for i in range (1 , len (arr)): j = i while j >= 1 and arr[j - 1 ] > arr[j]: arr[j - 1 ], arr[j] = arr[j], arr[j - 1 ] swap_count += 1 j -= 1 return swap_count
希尔排序(Shell Sort) 插入排序的优化,也称“递减增量排序算法”,先分组,分组内使用普通插入排序,逐渐增加每个分组内的元素数,最终一个分组内包含全部元素(step=1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 def shell_sort (arr ): swap_count = 0 step = len (arr) // 2 while step: for i in range (step, len (arr)): j = i while j - step >= 0 and arr[j - step] > arr[j]: arr[j - step], arr[j] = arr[j], arr[j - step] swap_count += 1 j -= step step //= 2 return swap_count
堆排序(Heap Sort) 先将输入数组转化为最大堆 ,然后每次将堆顶元素 和堆的最后一个未排序的元素 交换,然后将前面的元素继续堆化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 def heapify_max (arr, n, i ): left, right, target = i * 2 + 1 , i * 2 + 2 , i if left < n and arr[left] > arr[target]: target = left if right < n and arr[right] > arr[target]: target = right if target != i: arr[target], arr[i] = arr[i], arr[target] heapify_max(arr, n, target) def heap_sort (arr ): last_parent = (len (arr) - 2 ) // 2 for parent in range (last_parent, -1 , -1 ): heapify_max(arr, parent, len (arr)) for i in range (len (arr) - 1 , -1 , -1 ): arr[0 ], arr[i] = arr[i], arr[0 ] heapify_max(arr, i, 0 )
归并排序(Merge Sort) 先2个一组,组内排序,然后4个一组,组内排序(相当于合并两个有序列表),然后8个一组,组内排序,依次类推
稳定排序算法 复杂度:O(nlogn) 空间复杂度:O(n) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 def merge_sort (arr ): def merge (ll, rr ): l, r, r_end = ll, rr, min (rr + (rr - ll), len (arr)) merged = [] while l < rr and r < r_end: if arr[l] < arr[r]: merged.append(arr[l]) l += 1 else : merged.append(arr[r]) r += 1 for i in range (l, rr): merged.append(arr[i]) for i in range (r, r_end): merged.append(arr[i]) for i in range (len (merged)): arr[ll + i] = merged[i] i = 1 while True : for j in range (0 , len (arr), i << 1 ): merge(j, j + i) i <<= 1 if i >= len (arr): break
快速排序(Quick Sort) 每次取第一个未排序的值,将小于它的放到左边,大于它的放到右边,把该值放到中间,该值便确定。重复该过程直到全部排序完成
非稳定排序算法 复杂度:O(nlogn),最坏 O(nlogn) 空间复杂度:*O(n)*,根据实现方式不同 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 def quick_sort (arr ): sorted_indices = [False ] * len (arr) first_unsorted_idx = 0 while first_unsorted_idx < len (arr): pivot_idx = first_unsorted_idx low_store_idx = pivot_idx + 1 for i in range (pivot_idx + 1 , len (arr)): if sorted_indices[i]: break if arr[pivot_idx] > arr[i]: arr[i], arr[low_store_idx] = arr[low_store_idx], arr[i] low_store_idx += 1 arr[pivot_idx], arr[low_store_idx - 1 ] = arr[low_store_idx - 1 ], arr[pivot_idx] sorted_indices[low_store_idx - 1 ] = True while first_unsorted_idx < len (arr) and sorted_indices[first_unsorted_idx]: first_unsorted_idx += 1
计数排序(Counting Sort) 对一个小范围的整数排序
1 2 3 4 5 6 7 8 9 10 11 12 def counting_sort (arr ): base = min (arr) sort_arr = [0 ] * (max (arr) - base + 1 ) for i in range (len (arr)): sort_arr[arr[i] - base] += 1 idx = 0 for i in range (len (sort_arr)): for _ in range (sort_arr[i]): arr[idx] = base + i idx += 1
基数排序(Radix Sort) 对每一位分别排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 def radix_sort (arr ): max_ = max (arr) digit_count = 0 while max_: max_ //= 10 digit_count += 1 def get (num, digit ): ''' 获取一个整数的倒数第digit位数 @param digit: 0代表倒数第一位,1代表倒数第二位 ''' while digit: num //= 10 digit -= 1 return num % 10 for i in range (digit_count): buckets = [[] for _ in range (10 )] for n in arr: digit = get(n, i) buckets[digit].append(n) idx = 0 for bucket in buckets: for n in bucket: arr[idx] = n idx += 1
2022-11-23