算法打基础——快排

快排是各种排序中算法,非常重要的一种。其用到的主要思想也是分治法。

这一节主要涉及到的知识点有:1 基本快排  2.快排的直观及数学分析  3 随机化的快排及其严格的数学分析(数学分析在算法笔记中)

1 快排的基本内容

快排啊,其基本思想也是分治法。它是一种原地排序的算法,即和插入排序一样,不需要额外的空间去存储。比如归并排序就不行了,就需要额外空间去移动着来排序

快排的divide-and-conquer步骤:

1 分裂: 将数组用一个pivot x 分成两个部分,左半部分≤x,右半部分≥x

2.conquer: 递归的去处理分裂的子数组

3.合并:原地算法,直接就是合并好的

所以,快排的分割子算法就非常重要了,下面给出线性时间的分割算法

PARTITION(A, p, q)    ⊳A[p. . q]

x←A[p]                     ⊳pivot= A[p]

i←p

for j←p+ 1 to q

    do if A[j] ≤x

          then  i←i+1
              exchange  A[i] ↔A[j]

exchange A[p] ↔A[i]

return i

用语言去叙述这个过程就是,一个坐标j记录当前位,i记录分割位,当发现某个后面的数比pivot小的时候,就将分割位往后移动一位,然后交换当前分割位和当前位(因为分割位往后了一位,这个时候分割位指的一定是比pivot大的数,交换之后正好又满足分割的条件了)

下面给出一个分割的具体实例:

有了分割的代码,整个快排就比较好解决了

QUICKSORT(A, p, r)          ⊳Initial call: QUICKSORT(A,1,n)

   if  p< r
       then q←PARTITION(A, p, r)

              QUICKSORT(A, p, q–1)
       QUICKSORT(A, q+1, r)

2.快排的直观及数学分析

快排的分析,先来分析最坏情况。快排的最坏情况还是很容易出现的,输入是已经排序的,或者是逆序的都会导致最坏情况,因为选取的主元都是最大或最小值。这就引出了下面的递归式:

T(n)=T(0)+T(n-1)+Θ(n)

      =T(n-1)+Θ(n)

这个递归式用递归树来分析,很容易得到复杂度T(n) = Θ(n2)

最坏情况是非常糟糕的,那么最好情况以及那些没有达到最坏情况的时候呢?

当我们很幸运,每次分割都将数组平均分成两部分,此时我们得到最好情况:

T(n) = 2T(n/2) + Θ(n) = Θ(nlogn)

当分割都是0.1:0.9的时候呢?

显然树的两边是不平衡的,右边的高度要大,事实上,高度左边是log10n 右边是log10/9

所以复杂度T(n):    cnlog10n + O(n) ≤ T(n) ≤cnlog10/9n+ Ο(n)

所以复杂度仍是 Θ(nlgn)

3 随机化版本的快排

IDEA: Partition around a random element

其方法应该是很简单咯,就是随机选一个元素作为pivot。 主要就是证明这种方法的复杂度也是 Θ(nlgn),证明过程很多数学推导,所以我还是将其放在算法笔记当中。

最后附上自己写的快排:

 1 /////////////////////////CLRS   video lec4  快排/////////////////////////////////////////////////
 2 //一般情况下O(lg n)的复杂度,当输入是正序或者逆序的时候最坏情况O(n^2)  /////////////////////////////////////////////////////
 3 
 4 #include<iostream>
 5 #include<cstdlib>
 6 #include<ctime>
 7 using namespace std;
 8 
 9 #define random(x)(rand()%x)
10 
11 int findpar(int* arr,int p,int q)
12 {
13     int pivot = arr[p],temp,i,j,pos;
14     i=p;
15     for(j=p+1;j<=q;j++)
16     {
17         if(arr[j]<pivot)
18         {
19             temp=arr[++i];
20             arr[i]=arr[j];
21             arr[j]=temp;
22         }
23     }
24     temp=arr[i];
25     arr[i] = pivot;
26     arr[p]=temp;
27     return i;
28 }
29 void quicksort(int* arr,int p,int q)
30 {
31     int par = findpar(arr,p,q);
32     if((par-1)>p)
33         quicksort(arr,p,par-1);
34     if((par+1)<q)
35         quicksort(arr,par+1,q);
36     //也可以写成
37     /*
38     if(p<q){
39         int par = findpar(arr,p,q);
40         quicksort(arr,p,par-1);
41         quicksort(arr,par+1,q);
42     }*/
43 }
44 
45 int main()
46 {
47     int a[100];
48     srand((int)time(0));
49     int i,j,k;
50     for(i=0;i<100;i++)
51     {
52         a[i]=random(200);
53     }
54     quicksort(a,0,99);
55     for(i=0;i<100;i++)
56     {
57         cout<<a[i]<<" ";
58     }
59     cout<<endl;
60     return 0;
61 }
QuickSort

posted on 2013-10-20 15:25  soyscut  阅读(1897)  评论(0编辑  收藏  举报

导航