算法概述
快速排序(Quick Sort)是由英国计算机科学家Tony Hoare在1960年提出的一种排序算法。它采用分治策略(Divide and Conquer)来把一个序列分为两个子序列,然后递归地排序两个子序列。
快速排序的基本思想是:
- 从数列中挑出一个元素,称为"基准"(pivot)
- 重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面
- 递归地把小于基准值元素的子数列和大于基准值元素的子数列排序
算法步骤
- 选择基准值:从数组中选择一个元素作为基准值
- 分区操作:将数组重新排列,所有比基准值小的元素放在基准前面,比基准值大的放在后面
- 递归排序:递归地将小于基准值的子数组和大于基准值的子数组排序
Python实现
基础版本
python
def quick_sort_basic(arr):
"""
快速排序基础版本
时间复杂度: 平均O(n log n),最坏O(n²)
空间复杂度: O(log n)
"""
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2] # 选择中间元素作为基准
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
return quick_sort_basic(left) + middle + quick_sort_basic(right)
# 测试
arr = [3, 6, 8, 10, 1, 2, 1]
print("原始数组:", arr)
print("排序后:", quick_sort_basic(arr))原地排序版本(更高效)
python
def quick_sort_inplace(arr, low=0, high=None):
"""
原地快速排序版本
不创建新数组,节省空间
"""
if high is None:
high = len(arr) - 1
if low < high:
# 分区操作,返回基准值的正确位置
pivot_index = partition(arr, low, high)
# 递归排序左右两部分
quick_sort_inplace(arr, low, pivot_index - 1)
quick_sort_inplace(arr, pivot_index + 1, high)
def partition(arr, low, high):
"""
分区函数:将数组重新排列,返回基准值的最终位置
"""
# 选择最右边的元素作为基准
pivot = arr[high]
# 指向小于基准的元素的边界
i = low - 1
for j in range(low, high):
# 如果当前元素小于或等于基准
if arr[j] <= pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i] # 交换元素
# 将基准值放到正确的位置
arr[i + 1], arr[high] = arr[high], arr[i + 1]
return i + 1
# 测试原地排序版本
arr = [3, 6, 8, 10, 1, 2, 1]
print("原始数组:", arr)
quick_sort_inplace(arr)
print("原地排序后:", arr)三路快速排序(处理重复元素)
python
def quick_sort_3way(arr, low=0, high=None):
"""
三路快速排序
专门优化处理大量重复元素的情况
"""
if high is None:
high = len(arr) - 1
if low >= high:
return
# 三路分区
lt, gt, i = low, high, low
pivot = arr[low] # 选择第一个元素作为基准
while i <= gt:
if arr[i] < pivot:
arr[lt], arr[i] = arr[i], arr[lt]
lt += 1
i += 1
elif arr[i] > pivot:
arr[gt], arr[i] = arr[i], arr[gt]
gt -= 1
else:
i += 1
# 递归排序小于和大于基准的部分
quick_sort_3way(arr, low, lt - 1)
quick_sort_3way(arr, gt + 1, high)
# 测试三路快排(包含重复元素)
arr = [3, 6, 3, 1, 6, 2, 3, 1, 6, 3]
print("原始数组(含重复):", arr)
quick_sort_3way(arr)
print("三路快排后:", arr)算法复杂度分析
时间复杂度
- 最佳情况:O(n log n) - 每次分区都很平衡
- 平均情况:O(n log n)
- 最坏情况:O(n²) - 每次分区都极不平衡(如数组已排序)
空间复杂度
- 最佳情况:O(log n) - 递归调用栈的深度
- 最坏情况:O(n) - 不平衡分区导致的深递归
优化策略
1. 基准值选择优化
python
import random
def get_pivot(arr, low, high):
"""优化基准值选择:三数取中法"""
mid = (low + high) // 2
# 找到low, mid, high的中位数
if arr[low] > arr[mid]:
arr[low], arr[mid] = arr[mid], arr[low]
if arr[low] > arr[high]:
arr[low], arr[high] = arr[high], arr[low]
if arr[mid] > arr[high]:
arr[mid], arr[high] = arr[high], arr[mid]
return arr[mid]
def quick_sort_optimized(arr, low=0, high=None):
"""使用优化基准值选择的快速排序"""
if high is None:
high = len(arr) - 1
if high - low < 10: # 小数组使用插入排序
insertion_sort(arr, low, high)
return
if low < high:
pivot = get_pivot(arr, low, high)
pivot_index = partition_optimized(arr, low, high, pivot)
quick_sort_optimized(arr, low, pivot_index - 1)
quick_sort_optimized(arr, pivot_index + 1, high)
def insertion_sort(arr, low, high):
"""插入排序,用于小数组优化"""
for i in range(low + 1, high + 1):
key = arr[i]
j = i - 1
while j >= low and arr[j] > key:
arr[j + 1] = arr[j]
j -= 1
arr[j + 1] = key2. 尾递归优化
python
def quick_sort_tail_optimized(arr, low=0, high=None):
"""尾递归优化的快速排序"""
if high is None:
high = len(arr) - 1
while low < high:
pivot_index = partition(arr, low, high)
# 先递归较小的部分
if pivot_index - low < high - pivot_index:
quick_sort_tail_optimized(arr, low, pivot_index - 1)
low = pivot_index + 1
else:
quick_sort_tail_optimized(arr, pivot_index + 1, high)
high = pivot_index - 1性能测试
python
import time
import random
def test_performance():
"""测试不同实现的性能"""
sizes = [100, 1000, 10000]
for size in sizes:
test_arr = [random.randint(0, 1000) for _ in range(size)]
# 测试基础版本
arr1 = test_arr.copy()
start = time.time()
quick_sort_basic(arr1)
time1 = time.time() - start
# 测试原地版本
arr2 = test_arr.copy()
start = time.time()
quick_sort_inplace(arr2)
time2 = time.time() - start
# 测试优化版本
arr3 = test_arr.copy()
start = time.time()
quick_sort_optimized(arr3)
time3 = time.time() - start
print(f"数组大小: {size}")
print(f"基础版本: {time1:.6f}秒")
print(f"原地版本: {time2:.6f}秒")
print(f"优化版本: {time3:.6f}秒")
print("-" * 40)
# 运行性能测试
test_performance()实际应用场景
- 大规模数据排序:快速排序是处理大数据集最有效的排序算法之一
- 编程语言内置排序:很多语言的sort()函数基于快速排序实现
- 数据库查询优化:数据库系统使用快速排序进行记录排序
- 机器学习:特征排序和数据预处理
总结
快速排序是一种高效、通用的排序算法,具有以下特点:
- 平均时间复杂度为O(n log n)
- 原地排序(优化版本),空间效率高
- 可以通过多种策略优化基准值选择
- 适合处理大规模数据
- 是不稳定排序算法
通过合理选择基准值和优化递归策略,可以显著提高快速排序的性能,使其成为实际应用中最常用的排序算法之一。
本文由AI生成,内容仅供参考,请注意甄别