排序算法
排序算法就是将一组数据中的每个元素按照特定的顺序排序。 常见的排序算法很多,死记硬背不可取,熟悉原理吾所取。
1. 冒泡算法 bubble sort
循环数组每次选两个数比较,将较小的放置到前面,慢慢地将小的"浮出水面"。 冒泡排序的时间复杂度最差为\(O(n^2)\) ,最好为\(O(n)\) ;空间复杂度为\(O(1)\) 。
1 2 3 4 5 6 7 8 9 10 11 def bubble_sort (arr: list ) -> list: for i in range (1 , len (arr)): for j in range (0 , len (arr)-i): if arr[j] > arr[j+1 ]: arr[j], arr[j+1 ] = arr[j+1 ], arr[j] return arr
2. 选择排序 selection sort
选择排序, 最直观,直接在数组中找。 - 第一步,在数组中选择最小的元素放置到排序的起始位置, - 第二步,在剩余的元素中继续寻找最小元素,然后放置到已经排序的序列末尾 - 第三步,重复第二步
选择排序的时间复杂度最差\(O(n^2)\) ,最好为\(O(n^2)\) ;空间复杂度为\(O(1)\)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def select_sort (arr: list ) -> list: for i in range (len (arr) - 1 ): minIndex = i for j in range (i, len (arr)): if arr[j] < arr[minIndex]: minIndex = j if i != minIndex: arr[i], arr[minIndex] = arr[minIndex], arr[i] return arr
3. 插入排序 insertion sort
与打扑克牌的原理类似,它的工作原理为将待排列元素划分为「已排序」和「未排序」两部分, 每次从「未排序的」元素中选择一个插入到「已排序的」元素中的正确位置。 插入排序的时间复杂度最高为\(O(n^2)\) ,即原始数组倒序排列。 时间复杂度最好为\(O(n)\) ,空间复杂度为\(O(1)\) 。
算法稳定性 假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。则这个排序算法是稳定的! 插入排序是稳定的。
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 def insert_sort (arr: list ) -> list: for i in range (len (arr)): preIndex = i - 1 current = arr[i] while preIndex >= 0 and arr[preIndex] > current: arr[preIndex+1 ] = arr[preIndex] preIndex -= 1 arr[preIndex+1 ] = current print(i, arr) return arr
4. 希尔排序 shell sort
希尔排序 是对插入排序的一种优化,插入排序的原理可知,每次只能移动一个位置。 shell sort采用步长分割后再进行排序,本质是分组插入排序。具体实现是, 首先数组长度除以步长(gap),后续步长再除以gap的缩小值,直到以gap=1为步长排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 def shell_sort (arr: list ) -> list: import math gap = 1 while (gap < len (arr)/3 ): gap = gap*3 + 1 print('gap=' ,gap) while gap > 0 : for i in range (gap, len (arr)): temp = arr[i] j = i - gap while j >= 0 and arr[j] > temp: arr[j+gap] = arr[j] j -= gap arr[j+gap] = temp gap = math.floor(gap/3 ) return arr