快速排序(Quick Sort)是计算机科学中一种高效的排序算法,由英国计算机科学家托尼·霍尔(Tony Hoare)于1960年提出。它基于分治法(Divide and Conquer)策略来将一个序列分成较小和较大的两个子序列,然后递归地排序两个子序列。快速排序在平均情况下具有O(n log n)的时间复杂度,且常数因子较小,因此在实践中通常比其他O(n log n)算法更快。
快速排序的基本步骤
-
选择基准(Pivot Selection):从数组中选择一个元素作为基准值。选择的方法有多种,例如选择第一个元素、最后一个元素、中间的元素或随机选择一个元素。为了优化性能,可以采用“三数取中法”,即选取数组首尾和中间位置三个元素中的中位数作为基准。
-
分区(Partitioning):重新排列数组,使得所有比基准小的元素放在基准前面,所有比基准大的元素放在基准后面(相等的元素可以到任一边)。在这个过程结束后,该基准就位于其最终的位置。这个重要的操作称为分区操作。
-
递归调用:对基准左右两边的子数组分别进行递归调用快速排序。递归的基本条件是当子数组长度为0或1时停止递归,因为这样的数组已经是有序的。
-
合并结果:由于快速排序是原地排序算法,不需要像归并排序那样合并已经排序好的子数组,完成分区和递归调用后,整个数组就已经排好序了。
快速排序的实现
以下是使用Python编写的简单快速排序实现:
def quick_sort(arr):
if len(arr) <= 1:
return arr
else:
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 forx in arr if x > pivot]
return quick_sort(left) + middle + quick_sort(right)
# 示例调用
print(quick_sort([3,6,8,10,1,2,1]))
这段代码虽然简洁,但在实际应用中并不是最优的,因为它创建了额外的列表,增加了空间复杂度,并且对于含有大量重复元素的数据集效率较低。更优化的版本会直接在原始数组上进行操作,减少内存占用。
快速排序的优缺点
- 优点:快速排序是原地排序,不需要额外的大规模存储空间;在大多数情况下,它的表现非常出色,时间复杂度接近理论上的最优O(n log n)。
- 缺点:最坏情况下的时间复杂度为O(n^2),这发生在每次选择的基准都是最坏选择(如最小或最大元素),例如对已经排序的数组进行排序时。此外,快速排序是非稳定排序,意味着相同值的元素之间的相对顺序可能会改变。
通过引入随机化选择基准或者使用三数取中法,可以在很大程度上避免最坏情况的发生,使快速排序成为一种实用且高效的排序方法。