以下是各种排序算法的时间复杂度详细对比:
- 比较排序算法
O(n²) 复杂度算法
算法 平均情况 最好情况 最坏情况 空间复杂度 稳定性 说明
冒泡排序 O(n²) O(n) O(n²) O(1) ✓ 通过相邻元素交换
选择排序 O(n²) O(n²) O(n²) O(1) ✗ 每次选最小/最大值
插入排序 O(n²) O(n) O(n²) O(1) ✓ 适合小规模或基本有序
希尔排序 O(n log n) - O(n²) O(n log n) O(n²) O(1) ✗ 改进的插入排序
梳排序 O(n log n) O(n) O(n²) O(1) ✗ 冒泡排序的改进
O(n log n) 复杂度算法
算法 平均情况 最好情况 最坏情况 空间复杂度 稳定性 说明
快速排序 O(n log n) O(n log n) O(n²) O(log n) ✗ 分治,实际最快
归并排序 O(n log n) O(n log n) O(n log n) O(n) ✓ 稳定,适合外排序
堆排序 O(n log n) O(n log n) O(n log n) O(1) ✗ 原地排序,不稳定
TimSort O(n log n) O(n) O(n log n) O(n) ✓ Python/Java内置
- 非比较排序算法
线性复杂度算法
算法 平均情况 最好情况 最坏情况 空间复杂度 稳定性 适用条件
计数排序 O(n + k) O(n + k) O(n + k) O(k) ✓ k是数值范围
桶排序 O(n + k) O(n) O(n²) O(n + k) ✓ 数据均匀分布
基数排序 O(d·(n + k)) O(d·(n + k)) O(d·(n + k)) O(n + k) ✓ d是最大位数
- 详细分析
快速排序
python
"""
时间复杂度分析:
- 最优情况:每次分区都能均匀划分
T(n) = 2T(n/2) + O(n) = O(n log n)
- 最坏情况:每次选到最小或最大值作为枢纽
T(n) = T(n-1) + O(n) = O(n²)
- 平均情况:O(n log n)
空间复杂度:递归栈深度 O(log n)
"""
归并排序
python
"""
时间复杂度分析:
- 分治递归:T(n) = 2T(n/2) + O(n)
- 用主定理求解:O(n log n)
- 稳定且总是 O(n log n)
空间复杂度:需要额外数组 O(n)
"""
堆排序
python
"""
时间复杂度分析:
- 建堆:O(n)
- 每次堆调整:O(log n)
- 总复杂度:O(n) + n·O(log n) = O(n log n)
空间复杂度:原地排序 O(1)
"""
- 实际性能对比
小规模数据 (n < 50)
插入排序 > 选择排序 ≈ 冒泡排序 > 快速排序
原因:插入排序在小数据上常数因子小
中等规模数据 (50 < n < 1000)
快速排序 > 归并排序 > 堆排序 > 希尔排序
大规模数据 (n > 10000)
快速排序 > TimSort > 归并排序 > 堆排序
特定情况
· 基本有序数据:插入排序 O(n),TimSort O(n)
· 范围小的整数:计数排序 O(n + k)
· 外排序(内存不足):归并排序
· 需要稳定性:归并排序、TimSort
- Python中的排序实现
内置排序
python
# Python的sorted()使用TimSort
sorted_list = sorted(data) # O(n log n), 稳定
# list.sort()也是TimSort
data.sort() # 原地排序
TimSort特点
python
"""
TimSort = 归并排序 + 插入排序 + 优化
1. 将数组分成多个run(有序子序列)
2. 对小的run使用插入排序
3. 使用归并排序合并run
4. 自适应:利用已有顺序
复杂度:
- 最好:O(n)(已基本有序)
- 平均:O(n log n)
- 最坏:O(n log n)
- 空间:O(n)
"""
- 各算法代码实现
python
def bubble_sort(arr):
"""冒泡排序 O(n²)"""
n = len(arr)
for i in range(n):
swapped = False
for j in range(0, n-i-1):
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
swapped = True
if not swapped:
break
return arr
def selection_sort(arr):
"""选择排序 O(n²)"""
n = len(arr)
for i in range(n):
min_idx = i
for j in range(i+1, n):
if arr[j] < arr[min_idx]:
min_idx = j
arr[i], arr[min_idx] = arr[min_idx], arr[i]
return arr
def insertion_sort(arr):
"""插入排序 O(n²) - 最好O(n)"""
for i in range(1, len(arr)):
key = arr[i]
j = i-1
while j >= 0 and key < arr[j]:
arr[j+1] = arr[j]
j -= 1
arr[j+1] = key
return arr
def merge_sort(arr):
"""归并排序 O(n log n)"""
if len(arr) <= 1:
return arr
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
result = []
i = j = 0
while i < len(left) and j < len(right):
if left[i] <= right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
result.extend(left[i:])
result.extend(right[j:])
return result
def heap_sort(arr):
"""堆排序 O(n log n)"""
def heapify(arr, n, i):
largest = i
left = 2 * i + 1
right = 2 * i + 2
if left < n and arr[left] > arr[largest]:
largest = left
if right < n and arr[right] > arr[largest]:
largest = right
if largest != i:
arr[i], arr[largest] = arr[largest], arr[i]
heapify(arr, n, largest)
n = len(arr)
# 建堆
for i in range(n//2 - 1, -1, -1):
heapify(arr, n, i)
# 一个个取出元素
for i in range(n-1, 0, -1):
arr[i], arr[0] = arr[0], arr[i]
heapify(arr, i, 0)
return arr
def counting_sort(arr):
"""计数排序 O(n + k)"""
if not arr:
return []
max_val = max(arr)
min_val = min(arr)
range_size = max_val - min_val + 1
count = [0] * range_size
output = [0] * len(arr)
# 计数
for num in arr:
count[num - min_val] += 1
# 累加
for i in range(1, range_size):
count[i] += count[i-1]
# 输出
for i in range(len(arr)-1, -1, -1):
idx = arr[i] - min_val
output[count[idx] - 1] = arr[i]
count[idx] -= 1
return output
- 算法选择指南
根据需求选择:
· 通用排序:快速排序或TimSort
· 需要稳定:归并排序或TimSort
· 原地排序(内存少):堆排序或快速排序
· 小数据量:插入排序
· 整数,范围小:计数排序
· 数据基本有序:插入排序或TimSort
· 链表结构:归并排序
根据数据特征:
数据特征 | 推荐算法
----------------------|------------
随机 | 快速排序
基本有序 | 插入排序/TimSort
范围小的整数 | 计数排序
需要稳定排序 | 归并排序/TimSort
内存受限 | 堆排序
分布式/外排序 | 归并排序
- 性能测试示例
python
import time
import random
import matplotlib.pyplot as plt
def benchmark_algorithms():
"""性能基准测试"""
algorithms = {
'冒泡排序': bubble_sort,
'选择排序': selection_sort,
'插入排序': insertion_sort,
'快速排序': quick_sort_simple,
'归并排序': merge_sort,
'堆排序': heap_sort,
}
sizes = [100, 500, 1000, 5000, 10000]
results = {name: [] for name in algorithms}
for size in sizes:
arr = random.sample(range(size * 10), size)
for name, func in algorithms.items():
if size > 5000 and name in ['冒泡排序', '选择排序', '插入排序']:
# O(n²)算法太慢,跳过
results[name].append(None)
continue
arr_copy = arr.copy()
start = time.time()
func(arr_copy)
end = time.time()
results[name].append(end - start)
# 可视化
plt.figure(figsize=(12, 6))
for name, times in results.items():
valid_times = [t for t in times if t is not None]
valid_sizes = [sizes[i] for i, t in enumerate(times) if t is not None]
if valid_times:
plt.plot(valid_sizes, valid_times, marker='o', label=name)
plt.xlabel('数据量')
plt.ylabel('时间 (秒)')
plt.title('排序算法性能对比')
plt.legend()
plt.grid(True)
plt.show()
# benchmark_algorithms() # 取消注释运行测试
这个总结应该能帮助你根据具体情况选择合适的排序算法!