本文的主要从三个方面
- Python和JavaScript库排序函数使用技巧
- 常见排序算法盘点
- LeetCode相关题目刷题
排序函数使用技巧
在工作和研究中,大多数时候我们不需要手写一个排序函数,而是要非常熟悉排序函数的接口。Python自定义排序规则模板
```python def sort_rule(x, y): a, b = x + y, y + x if a > b: return 1 elif a < b: return -1 else: return 0
strs.sort(key = functools.cmp_to_key(sort_rule))
<a name="fWljm"></a># 常见排序算法盘点在不同领域,排序算法的实现各有千秋。总体来看,排序算法大致可分为十类:选泡插:选择排序、冒泡排序、插入排序<br />快归希堆:快速排序、归并排序、希尔排序、堆排序<br />桶计基:桶排序、计数排序、基数排序<a name="vof10"></a>## 时间复杂程度O(n^2)排序算法<a name="Nr5E8"></a>### 选择排序选择排序是一种简单直观的排序算法,无论什么数据进去都是 O(n²) 的时间复杂度。所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。<a name="Uoh0U"></a>#### 算法步骤首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。<br />再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。<br />重复第二步,直到所有元素均排序完毕。<a name="XOLGX"></a>#### 动图演示<a name="x90Bm"></a>#### Python代码实现```pythondef selectionSort(arr):for i in range(len(arr)-1):minIndex = ifor j in range(i+1, len(arr)):if arr[j]<arr[minIndex]:minIndex = jif i!=minIndex:arr[i],arr[minIndex] = arr[minIndex], arr[i]return arrL1 = [3,4,5,24,5,6,34,234,534]L2 = selectionSort(L1)print(L2)
冒泡排序
算法步骤
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
动图演示

python代码实现
def bubbleSort(arr):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 arrL1 = [3,4,5,24,5,6,34,234,534]L2 = bubbleSort(L1)print(L2)
插入排序
算法步骤
将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
动画图示

python代码实现
def insertionSort(arr):for i in range(len(arr)):preIndex = i - 1current = arr[i]while preIndex >= 0 and arr[preIndex]>current:arr[preIndex+1] = arr[preIndex]preIndex -=1arr[preIndex+1] = currentreturn arrL1 = [3,4,5,24,5,6,34,234,534]L2 = insertionSort(L1)print(L2)
时间复杂程度O(nlogn)级排序算法
快速排序
算法步骤
- 从数列中挑出一个元素,称为 “基准”(pivot);
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;
关于基准(pivot)的选择
- 选择第一个元素
- 选择最后元素
- 选择中间元素作为基础
动图示例

Python代码实现
以下代码中选择的基准是指定数组的第一个元素
def quickSort(arr, left=None, right=None):left = 0 if not isinstance(left,(int, float)) else leftright = len(arr)-1 if not isinstance(right,(int, float)) else rightif left < right:partitionIndex = partition(arr, left, right)quickSort(arr, left, partitionIndex-1)quickSort(arr, partitionIndex+1, right)return arrdef partition(arr, left, right):pivot = leftindex = pivot+1i = indexwhile i <= right:if arr[i] < arr[pivot]:swap(arr, i, index)index+=1i+=1swap(arr,pivot,index-1)return index-1def swap(arr, i, j):arr[i], arr[j] = arr[j], arr[i]
归并排序
希尔排序
堆排序
前K个大的元素,前K个小用堆排序算法解决
时间复杂度O(n)级排序算法
桶排序
计数排序
基数排序
工业级排序算法
Python排序算法剖析
JavaScript排序算法剖析
小结
| 排序算法 | 平均时间复杂程度 | 最好情况 | 最坏情况 | 空间复杂度 | 排序方式 | 稳定性 |
|---|---|---|---|---|---|---|
| 选择排序 | O(n^2) | O(n^2) | O(n^2) | O(1) | In-place | 不稳定 |
| 冒泡排序 | O(n^2) | O(n) | O(n^2) | O(1) | In-place | 稳定 |
| 插入排序 | O(n^2) | O(n) | O(n^2) | O(1) | In-place | 稳定 |
| 快速排序 | O(nlogn) | O(nlogn) | O(n^2) | O(logn) | In-place | 不稳定 |
| 归并排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(n) | Out-place | 稳定 |
| 希尔排序 | O(nlogn) | O(nlog^2(n)) | O(nlog^2(n)) | O(1) | In-place | 不稳定 |
| 堆排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(1) | In-place | 不稳定 |
| 桶排序 | O(n+k) | O(n+k) | O(n^2) | O(n+k) | Out-place | 稳定 |
| 计数排序 | O(n+k) | O(n+k) | O(n+k) | O(k) | Out-place | 稳定 |
| 基数排序 | O(nk) | O(nk) | O(nk) | O(n+k) | Out-place | 稳定 |
题目列表
剑指 Offer 45. 把数组排成最小的数 LCOF
class Solution:def minNumber(self, nums: List[int]) -> str:def sort_rule(x, y):a, b = x + y, y + xif a > b: return 1elif a < b: return -1else: return 0strs = [str(num) for num in nums]strs.sort(key = functools.cmp_to_key(sort_rule))return ''.join(strs)
283. 移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
class Solution:def moveZeroes(self, nums: List[int]) -> None:n = len(nums)left = right = 0while right < n:if nums[right] != 0:nums[left], nums[right] = nums[right], nums[left]left += 1right += 1
参考
本文参考以下链接进行撰写,仅作为学习用途,侵权删除
