快速排序(Quick Sort)
[简介]
快速排序(英语:Quicksort),又称划分交换排序(partition-exchange sort),最早由东尼·霍尔提出。在平均状况下,排序n个项目要Ο(n log n)次比较。在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见。事实上,快速排序通常明显比其他Ο(n log n)算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。
[算法复杂度]
仅针对非原地版本进行讨论
非原地版本的快速排序,在它的任何递归调用前需要使用O(n)空间。在最好的情况下,它的空间仍然限制在O(n),因为递归的每一阶中,使用与上一次所使用最多空间的一半,且
它的最坏情况是很恐怖的,需要
空间,远比数列本身还多。如果这些数列元素本身自己不是固定的大小,这个问题会变得更大;举例来说,如果数列元素的大部分都是不同的,每一个将会需要大约O(log n)为原来存储,导致最好情况是O(n log n)和最坏情况是O(n2 log n)的空间需求。
[核心算法]
快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。
步骤为:
- 从数列中挑出一个元素,称为"基准"(pivot),
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
[Source Code]
def quick_sort(alist=None): blist = alist[:] N = len(blist) if N <= 1: return blist pivot = blist[0] return quick_sort([x for x in blist[1:] if x < pivot]) + [pivot] + quick_sort([x for x in blist[1:] if x >= pivot])
[示意图]