快速排序(Quick Sort)

[简介]

  快速排序英语:Quicksort),又称划分交换排序(partition-exchange sort),最早由东尼·霍尔提出。在平均状况下,排序n个项目要Ο(n log n)次比较。在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见。事实上,快速排序通常明显比其他Ο(n log n)算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。

 

[算法复杂度]

  仅针对非原地版本进行讨论

  

  非原地版本的快速排序,在它的任何递归调用前需要使用O(n)空间。在最好的情况下,它的空间仍然限制在O(n),因为递归的每一阶中,使用与上一次所使用最多空间的一半,且

\sum _{i=0}^{\infty }{\frac {n}{2^{i}}}=2n

  它的最坏情况是很恐怖的,需要

\sum _{i=0}^{n}(n-i+1)=\Theta (n^{2})

  空间,远比数列本身还多。如果这些数列元素本身自己不是固定的大小,这个问题会变得更大;举例来说,如果数列元素的大部分都是不同的,每一个将会需要大约O(log n)为原来存储,导致最好情况是O(n log n)和最坏情况是O(n2 log n)的空间需求。

 

[核心算法]

  

  快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。

  步骤为:

  1. 从数列中挑出一个元素,称为"基准"(pivot),
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  3. 递归地(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])

 

[示意图]

 

posted @ 2016-08-30 16:56  Ice_Max  阅读(421)  评论(0编辑  收藏  举报