一、快速排序的算法思想
原理:快速排序基于分治策略。它的基本思想是选择一个元素作为“基准”,将待排序序列划分为两个子序列,使得左边的子序列中的所有元素都小于基准,右边的子序列中的所有元素都大于基准。这个划分操作被称为分区。然后,对左右两个子序列分别递归地执行快速排序,直到整个序列有序。
分区操作的关键在于确定基准元素在最终排序位置上,而它两侧的元素满足上述大小关系。实现时,可以通过一次遍历,将小于基准的元素交换至基准左侧,大于基准的元素交换至其右侧。这样,基准元素自然就落在了正确的位置上。
时间复杂度:最好情况是当每次分区都能均匀划分数组,即每次划分后左右子数组的长度相差不大时,快速排序的时间复杂度为 。平均情况时间复杂度也为 。最坏情况下当待排序数组已经是有序或接近有序时,每次分区只能得到一个子数组为空、另一个包含所有元素的情况,此时时间复杂度退化为。
空间复杂度:快速排序是一种递归算法,递归调用过程中需要使用栈来保存中间状态。在最坏情况下,递归深度为 n (完全不平衡的划分),因此空间复杂度为 。然而,实际应用中通过合理选择基准值和采用尾递归优化,递归深度往往远小于 n,平均空间复杂度接近 。
稳定性:不稳定,在分区过程中,相等的元素可能会因为与基准元素的相对位置改变而发生相对顺序的改变,导致排序后相等元素的顺序与原始顺序不一致。
二、快速排序的算法步骤
-
选择基准:从待排序序列中选择一个元素作为基准。通常可以选择数组的第一个元素、最后一个元素、中间元素或随机元素。
-
分区:遍历待排序序列,将所有小于基准的元素交换到基准之前,所有大于基准的元素交换到基准之后。最后将基准元素放置在其最终位置上,此时基准左侧元素均小于基准,右侧元素均大于基准。
-
递归排序:对基准左侧(小于基准的子序列)和右侧(大于基准的子序列)分别递归执行快速排序。
三、基于Python的快速排序实现
def quicksort(arr):
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 quicksort(left) + middle + quicksort(right)
# 示例
arr = [5, 2, 4, 6, 1, 3]
sorted_arr = quicksort(arr)
print(sorted_arr) # 输出: [1, 2, 3, 4, 5, 6]