直接选择排序 (Selection Sort)
- 核心思想:每一轮在未排序部分里找最小(或最大)的元素,放到已排序部分的末尾。
- 流程:
- 从数组的第一个位置开始,假设它是最小值。
- 遍历后面的所有元素,找到更小的元素,记录其下标。
- 一轮结束后,将最小元素和当前位置元素交换。
重复以上步骤,直到所有元素排序完成。
python
def selection_sort(a):
"""直接选择排序:每轮把未排序区的最小值放到前面。"""
n = len(a)
for i in range(n - 1):
min_idx = i
for j in range(i + 1, n):
if a[j] < a[min_idx]:
min_idx = j
if min_idx != i:
a[i], a[min_idx] = a[min_idx], a[i]
- 平均时间复杂度:O(N^2)
直接插入排序 (Insertion Sort)
- 核心思想:像打扑克牌一样,把新的牌插入到已经排好序的牌堆中合适的位置。
- 流程:
- 默认第一个元素已经有序。
- 取下一个元素(
key
),和前面有序区的元素依次比较,找到合适位置插入。 - 插入时要把比它大的元素依次向后移动。
- 重复直到所有元素处理完。
python
def insertion_sort(a):
"""直接插入排序:像插牌一样,把当前元素插到有序区合适位置。"""
for i in range(1, len(a)):
key = a[i] # "下一个元素"
j = i - 1
while j >= 0 and a[j] > key:
a[j + 1] = a[j]
j -= 1
a[j + 1] = key
- 平均时间复杂度:O(N^2)
冒泡排序 (Bubble Sort)
- 核心思想:相邻元素两两比较,大的往后"冒泡",小的往前"沉"。
- 流程:
- 从头到尾,比较相邻两个数,如果前一个比后一个大,就交换。
- 一趟结束后,最大值会沉到最后。
- 对剩余未排序部分重复这个过程,直到只剩一个元素。
python
def bubble_sort(a):
"""冒泡排序(含短路优化):一趟把最大值"冒"到末尾。"""
n = len(a)
for i in range(n - 1):
swapped = False
for j in range(0, n - 1 - i):
if a[j] > a[j + 1]:
a[j], a[j + 1] = a[j + 1], a[j]
swapped = True
if not swapped: # 已经有序,提前结束
break
- 平均时间复杂度:O(N^2)
快速排序 (Quick Sort)
- 核心思想:分治法。选一个"基准值 (pivot)",把数组分成两部分:小于基准值的放左边,大于基准值的放右边,然后递归排序。
- 流程:
- 在数组中选择一个基准值(常见做法是第一个或最后一个元素)。
- 将数组划分为左右两个子区间:
- 左边都是小于等于基准值的元素;
- 右边都是大于基准值的元素。
- 对左右两个子区间分别递归执行快速排序。
- 最终拼接:左子区间 + 基准值 + 右子区间。
python
def quick_sort(a):
"""快速排序(就地、双向指针分区;不使用切片,避免额外 O(n) 空间)。"""
def _qs(lo, hi):
if lo >= hi:
return
i, j = lo, hi
pivot = a[(lo + hi) // 2] # 取中点作基准(降低退化概率)
while i <= j:
while a[i] < pivot:
i += 1
while a[j] > pivot:
j -= 1
if i <= j:
a[i], a[j] = a[j], a[i]
i += 1
j -= 1
if lo < j:
_qs(lo, j)
if i < hi:
_qs(i, hi)
_qs(0, len(a) - 1)
- 平均时间复杂度:O(N logN)
希尔排序
待补充
python
对比
算法 | 最好时间 | 平均时间 | 最坏时间 | 额外空间 | 稳定性 | 备注 |
---|---|---|---|---|---|---|
直接选择排序 | O(n^2) | O(n^2) | O(n^2) | O(1) | 不稳定 | 交换次数 ≤ (n-1),比较次数固定约 n(n-1)/2 |
直接插入排序 | O(n) | O(n^2) | O(n^2) | O(1) | 稳定 | 对"基本有序"数据非常高效 |
冒泡排序(含短路) | O(n) | O(n^2) | O(n^2) | O(1) | 稳定 | 已有序时一趟即可结束 |
快速排序(原地) | O(n log n) | O(n log n) | O(n^2) | 期望 O(log n)(递归栈) | 不稳定 | 随机/三数取中可降低退化概率 |