算法导论-排序(二)快速排序、随机化快速排序

目录                                                                 

     一、本文介绍

     二、快速排序

     三、随机化快速排序

     四、完整源码

     五、参考资料

内容                                                                

     一、本文介绍                                                                     

           主要内容分为两部分,一部分是介绍快速排序算法,分析其在最好、最坏以及最好最差交替出现状况下的算法效率;另外一部分则是介绍随机化快排算法,以及分析其算法复杂度。最后给出c++实现代码。html

     二、快速排序                                                                           

        快速排序也是基于分治思想,首先把要排序的数组分为两份,而后再分别对分好的子数组进行快速排序。当子数组为1个元素时递归介绍,排序完成。快速排序属于“原地排序”,就是说在原有的数组内存上排序、不占用其余内存。归并排序就不同,它则须要额外的空间来进行归并排序操做。下图是快速排序的分治思想:
ios

由上图能够知道,快速排序里面最关键的就是第一步:分化(Partition)的步骤,这是该算法处理问题的核心。因此咱们能够把快排当作是递归地划分数组,就像归并排序是递归地合并数组同样。关于Paritition的具体算法,目前有好几种,其伪代码稍有不一样可是它们的原理都是同样的。固然最重要的一点是分化(Partition)的算法复杂度都是线性的,也就是O(n)。下面是分化(Partition)的一种伪码:c++

1 Partition(A,p,q)
2     x   <-  A[p]     //选第一个为主元
3     i   <-   p
4     for j  <- p+1  to q
5         do if  A[j] <  x   //小于主元的数据放在左边
6                   then i  <-  i+1
7                          exch A[i] <-> A[j]  // 交换A[i]   A[j] 
8     exch A[p] <-> A[i]  // 交换
9     return i  //返回划分好后主元索引

 

分划好后就是简单的递归,下面是快排的伪代码:算法

1 QuickSort(A,p,q)
2     if p < q  //不知足就介绍递归
3         then  r <- Partition(A,p,q) //分划
4                 QuickSort(A,p , r-1) //递归快排左子数组
5                 QuickSort(A , r+1 ,q)  //递归快排右子数组

   接下来分析快排的算法效率

    1)最坏状况下分析

         当输入序列是正序或者是反序的时候,效率最坏,这时效率是Θ(n2)编程

    2)  最优状况下分析

       其余状况下的算法效率趋向于Θ(nlgn)数组

  那么咱们如何保证咱们老是效率处于最优状况下的呢?这就是随机化快速排序须要解决的问题。dom

     三、随机化快速排序                                                                  

        咱们已经知道,若输入自己已被排序,那么对于快排来讲就糟了。那么如何避免这样的状况?一种方法时随机排列序列中的元素;另外一种方法时随机地选择主元(pivot)。这即是随机化快速排序的思想,这种快排的好处是:其运行时间不依赖于输入序列的顺序。ide

      经分析, 随机化快排的算法效率是Θ(nlgn)。性能

    实现:咱们只需在选取主元时加入随机因素便可。其余与快排同样测试

     下面是分化(Partition)编程(c++)实现

1 int  Random_Partition(vector<T> &A,int p,int q)
2 {
3     int i=rand()%(q-p)+p;  //此行与快排不一样、加入随机数参数器
4     Swap(A[i],A[p]);         //此行与快排不一样、随机选取主元
5      return Partition(A,p,q);//这次与快速排序同样
6 }

 

// 随机化快速排序
1
void Random_Quick_Sort(vector<T> &A,int p,int q) 2 { 3 if (p<q) 4 { 5 int i=Random_Partition(A,p,q); 6 Random_Quick_Sort(A,p,i-1); 7 Random_Quick_Sort(A,i+1,q); 8 } 9 }

     四、完整源码                                                                            

       下面源码包含以前讨论过的插入排序、归并排序算法。最后给出时间比较

      CTimer.h  (测试间的头文件实现,不懂无需纠结)

 1 #ifndef CTIMER_HH
 2 #define CTIMER_HH
 3 class CTimer
 4 {
 5 public:
 6     CTimer()
 7     {
 8         QueryPerformanceFrequency(&m_Frequency);
 9         Start();
10     }
11     void Start()
12     {
13         QueryPerformanceCounter(&m_StartCount);
14     }
15     double End()
16     {
17         LARGE_INTEGER CurrentCount;
18         QueryPerformanceCounter(&CurrentCount);
19         return double(CurrentCount.LowPart - m_StartCount.LowPart) *1000/ (double)m_Frequency.LowPart;
20     }
21     void ShowNow()
22     {
23         LARGE_INTEGER CurrentCount;
24         QueryPerformanceCounter(&CurrentCount);
25         cout<<"Timer Count is:"<<double(CurrentCount.LowPart - m_StartCount.LowPart)*1000 / (double)m_Frequency.LowPart<<endl;
26     }
27 private:
28     LARGE_INTEGER m_Frequency;
29     LARGE_INTEGER m_StartCount;
30 };
31 #endif
View Code

     Sort.h  (排序算法[插入排序、归并排序、快速排序、随机化快速排序]实现头文件)

  1 #ifndef SORT_HH
  2 #define SORT_HH
  3 template<typename T >//带模板
  4 class Sort
  5 {
  6     public:
  7         void insertion_sort(vector<T> &A);//插入排序
  8         void merge_sort(vector<T> &A,int p,int r);//归并排序
  9         void print_element(vector<T> A);//打印数组
 10         void Quick_Sort(vector<T> &A,int p,int q);//快速排序
 11         int Partition(vector<T> &A,int p,int q);//分划
 12         void Swap(T &m,T &n);//交换数据
 13         void Random_Quick_Sort(vector<T> &A,int p,int q);//随机化快速排序
 14         int Random_Partition(vector<T> &A,int p,int q);//随机化分划
 15     private:
 16         void merge(vector<T> &A,int p,int q,int r);// 归并排序子程序
 17 };
 18 template<typename T>//插入排序
 19 void Sort<T>::insertion_sort(vector<T> &A)
 20 {
 21     int i,j;
 22     T key;
 23     int len=A.size();
 24     for (j=1;j<len;j++)
 25     {
 26         i=j-1;
 27         key=A[j];
 28         while (i>=0&&A[i]>key)
 29         {
 30             A[i+1]=A[i];
 31             i--;
 32         }
 33         A[i+1]=key;
 34     }
 35 }
 36 
 37 template<typename T>// 归并排序子程序
 38 void Sort<T>::merge(vector<T> &A,int p,int q,int r)
 39 {
 40     int n1=q-p+1;
 41     int n2=r-q;
 42     T *L=new T[n1+1];
 43     T *R=new T[n2+1];
 44 
 45     for (int i=0;i<n1;i++)
 46         L[i]=A[i+p];
 47     for (int i=0;i<n2;i++)
 48         R[i]=A[i+q+1];
 49 
 50     L[n1]=R[n2]=INT_MAX;
 51 
 52     int i=0,j=0;
 53     for (int k=p;k<=r;k++)
 54     {
 55         if (L[i]>R[j])
 56         {
 57             A[k]=R[j];
 58             j++;
 59         }
 60         else
 61         {
 62             A[k]=L[i];
 63             i++;
 64         }
 65     }
 66 
 67     delete[] L;
 68     delete[] R;
 69 
 70 }
 71 
 72 template<typename T>//归并排序
 73 void Sort<T>::merge_sort(vector<T> &A,int p,int r)
 74 {
 75     if (p<r)
 76     {
 77         int mid=(p+r)/2;
 78         merge_sort(A,p,mid);
 79         merge_sort(A,mid+1,r);
 80         merge(A,p,mid,r);
 81     }
 82 }
 83 
 84 template<typename T>//交换数据
 85 void Sort<T>::Swap(T &m,T &n)
 86 {
 87     T tmp;
 88     tmp=m;
 89     m=n;
 90     n=tmp;
 91 }
 92 
 93 /***********快速排序分划程序*************/
 94 template<typename T>
 95 int Sort<T>::Partition(vector<T> &A,int p,int q)
 96 {
 97     T x=A[p];
 98     int i=p;
 99     for (int j=p+1;j<=q;j++)
100     {
101         if (A[j]<x)
102         {
103             i=i+1;
104             Swap(A[i],A[j]);
105         }
106     }
107     Swap(A[p],A[i]);
108     return i;
109 }
110 template<typename T>//快速排序
111 void Sort<T>::Quick_Sort(vector<T> &A,int p,int q)
112 {
113     if(p<q)
114     {
115         int i=Partition(A,p,q);
116         Quick_Sort(A,p,i-1);
117         Quick_Sort(A,i+1,q);
118     }
119 }
120 
121 template<typename T>//随机化快速排序分划程序
122 int Sort<T>::Random_Partition(vector<T> &A,int p,int q)
123 {
124     int i=rand()%(q-p)+p;
125     Swap(A[i],A[p]);
126      return Partition(A,p,q);
127 }
128 
129 template<typename T>//随机化快速排序
130 void Sort<T>::Random_Quick_Sort(vector<T> &A,int p,int q)
131 {
132     if (p<q)
133     {
134         int i=Random_Partition(A,p,q);
135         Random_Quick_Sort(A,p,i-1);
136         Random_Quick_Sort(A,i+1,q);
137     }
138 }
139 
140 template<typename T>//打印数组
141 void Sort<T>::print_element(vector<T> A)
142 {
143     int len=A.size();
144     for (int i=0;i<len;i++)
145     {
146         std::cout<<A[i]<<" ";
147     }
148     std::cout<<std::endl;
149 }
150 #endif
View Code

Sort_main.cpp (测试主程序)

 1 #include <iostream>
 2 #include <vector>
 3 #include <time.h>
 4 #include <Windows.h>
 5 using namespace std;
 6 #include "Sort.h"
 7 #include "CTimer.h"
 8 
 9 #define  N 10   //排序数组大小
10 // 随机参数排序数组
11 void Random(vector<int> &a,int n)  
12 {  
13     int i=0;  
14     srand( (unsigned)time( NULL ) );  
15     while(i<n)  
16     {  
17         a[i++]=rand();  
18     }  
19 }  
20 int main()
21 {
22     Sort<int> sort1;
23     CTimer t;
24     vector<int > vec_int(N);
25     Random(vec_int,N);
26     cout<<"源数组:";
27     sort1.print_element(vec_int);
28     t.Start();
29     sort1.Quick_Sort(vec_int,0,vec_int.size()-1);
30     cout<<"快速排序:"<<t.End()<<"ms"<<endl;
31     sort1.print_element(vec_int);
32     Random(vec_int,N);
33     t.Start();
34     sort1.Random_Quick_Sort(vec_int,0,vec_int.size()-1);
35     cout<<"随机化快速排序:"<<t.End()<<"ms"<<endl;
36     sort1.print_element(vec_int);
37     Random(vec_int,N);
38     t.Start();
39     sort1.insertion_sort(vec_int);
40     cout<<"插入排序:"<<t.End()<<"ms"<<endl;
41     sort1.print_element(vec_int);
42     Random(vec_int,N);
43     t.Start();
44     sort1.merge_sort(vec_int,0,vec_int.size()-1);
45     cout<<"归并排序:"<<t.End()<<"ms"<<endl;
46     sort1.print_element(vec_int);
47 
48     system("PAUSE");
49     return 0;
50 }
View Code

   输出:

 

排序算法时间比较:

数组大小 快速排序(ms) 随机化快速排序(ms) 插入排序(ms) 归并排序(ms)
10 0.0054523 0.00673552 0.00481085

0.0189227

100 0.108084 0.107763 0.377492 0.232845
1000 1.71427 1.47212 49.5864 2.67323
10000 34.795 19.2226 3542.74 30.3318
100000 232.691 233.02 352846 350.414
1000000 3032.3 3273.46 ......(太大、没测) 4017.02

自我小结:对随机产生的数组进行排序,1)能够发现插入排序没有优点、特别是数组比较大时耗时太多;2)快速排序、随机化快速排序、归并排序性能不错,然而两种快排比归并排序性能好点;3)当数据量变大时,能够看出性能排序为快速排序、随机化快速排序、归并排序、插入排序;4)因为这里的数组是由随机数产生的,没有显示出随机化快速排序的优点,可是当数组为已排序状况下随机化快排将比快排性能好。

     五、参考资料                                                                             

      【1】http://blog.csdn.net/xyd0512/article/details/8259382

      【2】http://blog.csdn.net/kenden23/article/details/14558231

      【3】http://www.cnblogs.com/lidabo/archive/2013/01/08/2850418.html

相关文章
相关标签/搜索