算法导论之快速排序文档

时间:2021-10-18 04:31:31

对于包含n个数的输入数组来说,快排是一种最坏情况下时间复杂度为O(n*n)的排序算法。虽然最坏时间复杂度很差,但是快排通常是实际排序中的首选,

以为他的平均性能非常好,它的期望时间复杂度为O(nlgn),而且O(nlgn)中隐含的常数因子非常小。

快排分为两个部分的函数来实现:函数QUICKSORT(A,p,r)和函数PARTITION(A,p,r)


函数QUICKSORT(A,p,r)体现的是总的快排的功能,函数的伪代码如下:

QUICKSORT(A,p,r)(A表示的数组名,p是数组的下标,r是数组的上标,即就是对数组A[p,r]进行排序)

QUICKSORT(A,p,r)

If p<r

  q=PARTITION(A,p,r);

  QUICKSORT(A,p,q-1);

QUICKSORT(A,q+1,r);


看函数的实现过程,其实就是运用了三步分治法进行排序。找到合适的位置,将数组分成两部分,然后对每一部分再次调用此函数,不断重复,直到数组中的元素有序。

另外一个函数PARTITION(A,p,r),此函数的实现体现的正好是快排算法的核心。算法的思想是:以数组的最后一个元素为标杆,每次进行比较和交换,每一轮过后,结果是使得小于等于此元素的所有数组元素被放置在数组的一端,剩下的大于此元素的所有元素被放置在数组的另一端,两端的分界线刚好是原数组的最后一个元素,完成调换过程之后,再对此元素进行调换,将其调换到数组的分界线所处的位置,此时,相当于此元素一遍的元素全都大于此元素,另一边的所有元素都小于此元素,即就实现了排序。


PARTITION(A,p,r)函数的伪代码如下:

PARTITION(A,p,r)

x=A[r];

i=p-1;

for j=p to r-1

  if A[j]<=x

i=i+1;

exchange A[i] with A[j];

exchange A[i+1] with A[r];

return i+1;


快排的随机化版本:

在讨论快排的平均情况性能的时候,我们的前提假设是:输入数据的所有排列都是等概率的,但是在实际工程中,这种假设并不总是成立,因此我们可以通过在算法中引入随机性,来使得算法对所有的输入都能获得较好的期望性能。从上面的描述可以看到,每次分成两部分的标准是A[r],即就是要进行排序的这一段数组A[p,r]的最后一个元素的值,很容易可以得到,如果每次分的两部分的长度越相近,最后得到的程序运行时间就越短。但实际工程中的A[r]往往呈现出一种有规律的迹象,因此,我们要对原来的程序稍加改动来实现随机化。

新增加一个函数:RANDOMIZED-PARTITION(A,p,r)


RANDOMIZED-PARTITION(A,p,r)函数的伪代码如下:

RANDOMIZED-PARTITION(A,p,r)

i=RANDOM(p,r);    //每次在A[p,r]之间选择一个数来与元素A[r]进行交换

exchange A[r] with A[i];

return PARTITION(A,p,r);


此函数的功能就是每次用产生的随机的值换掉原始的A[r]的值。

此时新的快排不再调用PARTITION,而是调用RANDOMIZED-PARTITION


RANDOMIZED-PARTITION(A,p,r):

If p<r

  q=PARTITION(A,p,r);

  RANDOMIZED-PARTITION(A,p,q-1);

RANDOMIZED-PARTITION(A,q+1,r);