快速排序

之前的文章介绍过冒泡算法。在每一轮冒泡排序中,无序序列通过元素间的不断的交换,使无序集合中最大或最小的元素不断沉底,最后这个元素就变成了有序序列的第一个元素。冒泡算法的思想是非常朴素,它的时间复杂度为O(n2),这不能满足速度上的要求。所以有人就想到了优化这个算法的办法,也就这篇文章要介绍的快速排序算法。

我们可以发现冒泡排序的流程是这样的,在每一轮排序中,它已经知道了元素要被交换到的位置,然后再在无序序列中不断交换,使合适的元素到达这个位置。那么,有没有办法让先确定元素,再想办法确定元素的位置,这样,每确定一个元素X,序列就会变成如下这样:

这样的好处是,我们可以使用分治算法对其进行处理,减少比较轮数。每一次都将未排序部分分成两部分,比X小的部分和比X大的部分,下一轮排序再对未划分部分进一步划分,直到分无可分为止。

时间复杂度

一个长度为n的序列平均需要logn轮,每论需要遍历n个元素,所以快算排序算法的时间复杂度为O(nlogn)。

如何确定一个元素的位置

确定元素X的方法是,从无序序列的两端向中间逼近,(假设是升序排列),在逼近过程中如果X左边有比X大的数,就和X交换,同样,如果X右边有比X小的元素,也交换,这样当在序列中间相遇时,比X大的数都在X 右边,比X小的数都在X左边,那么X的最终位置也就确定下来了

最坏情况

快速排序最坏的情况是原始序列的排序方向和目标排序方向相反,如将{1,2,3,4,5}排位降序序列,这种情况下每一轮快速排序都只能确定一个元素的位置,快速排序的时间复杂度退化为O(n2)。

快速排序代码

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 int num[] = {72,34,90,5,88,58,71,71,27,24,3};
 5 void quickSort(int*a,int left,int right)
 6 {
 7     int x = a[left];
 8     int p1 = left,p2 = right+1;
 9     if(p1>=p2) return;
10     while(p1<p2)
11     {
12         while(p1<p2&&a[--p2]>=x);
13         swap(a[p1],a[p2]);
14         while(p1<p2&&a[++p1]<=x);
15         swap(a[p1],a[p2]);
16     }
17     quickSort(a,left,p1-1);
18     quickSort(a,p1+1,right);
19     return;
20 }
21 int main()
22 {
23     quickSort(num,0,10);
24     for(int i=0;i<11;i++)
25         cout<<num[i]<<" ";
26     return 0;
27 }