快速排序算法

快速排序算法最早由图灵奖获得者Tony Hoare设计出来的,他在形式化方法理论以及ALGOL60编程语言的发明中都有卓越的贡献,是上世纪最伟大的计算机科学家之一。

时间复杂度:O(n*lgn)
最坏:O(n^2)
空间复杂度:O(n*lgn)
不稳定。

要注意很多细节问题,如:

  1. 我们知道,快速排序的分治partition过程有两种方法,一种方法是两个指针从首尾位分别向中间扫描的方法(大多数的人和一般的教材采用的是这第二种首尾向中间扫描法,算法导论的思考题7-1,P103页),这种方式是Hoare的最原始设计思想,俗称Hoare版本,需要注意的是partition操作里面一定要从右面开始,即,while(l<h && data[h]>=pivot)h--;
          XXXX;
          while(l<h && data[l]<=pivot)l++;
          XXXX; 的顺序结构。另外
    一种是上面所述的两个指针索引一前一后逐步向后扫描的方法(算法导论
    P95页上采用的是这种方法)
  2. partition过程中,要注意一些边界值问题。如i、j索引的初始化,for循环中,j从数组中第一个位置到倒数第二个位置h-1处,且是当data[j]<=privot(是小于等于,非小于),然后找到了之后,i++,再交换。最后还有一次data[i+1]与data[h]的交换。最后,便是返回值的问题,返回i+1。
  3. 第三个要注意的方面是递归处。if(l<h),才进入递归。

    主要要注意的问题就是上述三个方面。只要把握好细节,那么快速排序算法,二十几行自能搞定。

对于版本一可以引用 http://developer.51cto.com/art/201403/430986.htm 的图片,这样更容易理解。

版本一伪代码(Hoare版本)
HOARE-PARTITION(A, p, r)
 1  x ← A[p]
 2  i ← p - 1
 3  j ← r + 1
 4  while TRUE
 5      do repeat j ← j - 1
 6           until A[j] ≤ x
 7         repeat i ← i + 1
 8           until A[i] ≥ x
 9         if i < j
10            then exchange A[i] ↔ A[j]
11            else return j</strong></span>

版本二伪代码:
QUICKSORT(A, p, r)
1 if p < r
2    then q ← PARTITION(A, p, r)   //关键
3         QUICKSORT(A, p, q - 1)
4         QUICKSORT(A, q + 1, r)

数组划分
快速排序算法的关键是PARTITION过程,它对A[p..r]进行就地重排:
PARTITION(A, p, r)
1  x ← A[r]
2  i ← p - 1
3  for j ← p to r - 1
4       do if A[j] ≤ x
5             then i ← i + 1
6                  exchange A[i] <-> A[j]
7  exchange A[i + 1] <-> A[r]
8  return i + 1</span></strong>


下面是实际的代码(可运行,我在code::blocks运行成功)

这几种方式在于分区操作的不同而已,其他都相同。

partition1:是原始的Hoare版本,即两个指针分别由首尾向中间进行扫描

partition1_1:是原始Hoare版本的另一版本,同理上面

partition2:是后来的改版,即两个指针索引从首部一前一后逐步向后扫描

可以将 quicksort函数中的分区操作由上面的这几种方式代替即可。


#include <iostream>
#include <stdio.h>

using namespace std;

void swap(int* a,int* b){
    int temp = *a;
    *a = *b;
    *b = temp;
}
int partition2(int data[],int l,int h){
    int i=l-1,j;
    int pivot = data[h];
    for(j=l;j<h;j++){
        if(data[j]<=pivot){
            i++;
            swap(&data[i],&data[j]);
        }
    }
    swap(&data[h],&data[i+1]);
    return i+1;
}

int partition1(int data[],int l,int h){
    int pivot = data[l];
    while(l<h){
        while(l<h && data[h]>=pivot)h--;
        data[l]=data[h];
        while(l<h && data[l]<=pivot)l++;
        data[h]=data[l];
    }
    data[l]=pivot;
    return l;
}
int partition1_1(int data[],int l,int h){
    int pivot = data[l];
    while(l<h){
        while(l<h && data[h]>=pivot)h--;
        swap(&data[l],&data[h]);
        while(l<h && data[l]<=pivot)l++;
        swap(&data[l],&data[h]);
    }
    return l;
}
void quicksort(int data[],int l,int h){
    if(l<h){
        int pivot = partition2(data,l,h);
        quicksort(data,l,pivot-1);
        quicksort(data,pivot+1,h);
    }
}
int main()
{
    int data[] = {87,45,12,32,56,89,98,1,34,65};
    quicksort(data,0,9);
    for(int t=0;t<10;t++){
        cout<<data[t]<<" "<<endl;
    }
    return 0;
}

如果未来我看不懂代码啦,请自己去看算法导论!一定能看懂

你可能感兴趣的:(快速排序)