再来看看快速排序

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

void quickSort(vector<int> &vec,int l,int u){
    int i , m;
    if( l>=u) return ;
    m = l;
    for(i = l+1; i <= u; i++){
        if(vec[i] < vec[l]){
            ++m;
            swap(vec[m],vec[i]);
        }
    }
    swap(vec[m],vec[l]);

    quickSort(vec,l,m-1);
    quickSort(vec,m+1,u);
}

void printInfo(vector<int> vec){
    vector<int>::iterator it = vec.begin();
    for(; it != vec.end(); it++)
        cout << *it << " ";
    cout << endl;
}

int main(){
    vector<int> vec;
    for(int i = 1; i <= 100; i++)
        vec.push_back(i);
    cout << "----------before shuffle-----------" << endl;
    printInfo(vec);
    
    random_shuffle(vec.begin(),vec.end());
    cout << "----------after shuffle-----------" << endl;
    printInfo(vec);

    quickSort(vec,0,99);
    cout << "----------after quickSort-----------" << endl;
    printInfo(vec);

    getchar();
    return 0;
}

 

结果:

-----------------------------------------------------------------------------------------------------------------------------------------

在排序中,有几种比较重要的排序。快速排序,堆排序,归并排序。

查找中比较重要的哈希查找(因为时间复杂度是0(1)),二分查找(O(logn))。

 

上一次写的快速排序的博客是根据严蔚敏老师的教材来写的,现在觉得有点不平易近人,晦涩难懂。

今天就重新来整理一下快速排序,希望自己能够做到对快排信手拈来,熟记于心。大不了,背下来也可以。

 

 1 void quicksort(int l, int u){
 2     int i, m;
 3     if(l >= u) return;
 4     m = l;
 5     for(i = l+1; i<= u; i++)
 6         if(x[i] < x[l]) 
 7             swap(++m, i);
 8 
 9     swap(l, m);
10 
11     quicksort(l, m-1);
12     quicksort(m+1, u);
13 
14 }

这是Jon Bently在beautiful code里的代码。

最核心的代码就是for循环那一块了,在for循环之后,[ l + 1, m ]里全是比pivot小的数(pivot是x[l]),然后通过swap(l,m)将下标为m和l的数字交换。

这样就完成了一边partition,下标m之前的数全都小于pivot,下标m之后的数全都大于pivot。

 

但是有一个Bug。当存在很多与pivot相等的数时,这些数会整体被分在m的左边或者m的右边。

如果我们想在一个partition中分成三部分,即左边部分是小于pivot,中间等于pivot,右边全都大于pivot。然后在下一次partition的时候只对左右两部分调用。

    private static void sort(Comparable[] a, int lo, int hi) { 
        if (hi <= lo) return;
        int lt = lo, gt = hi;
        Comparable v = a[lo];
        int i = lo;
        while (i <= gt) {
            int cmp = a[i].compareTo(v);
            if      (cmp < 0) exch(a, lt++, i++);
            else if (cmp > 0) exch(a, i, gt--);
            else              i++;
        }

        // a[lo..lt-1] < v = a[lt..gt] < a[gt+1..hi]. 
        sort(a, lo, lt-1);
        sort(a, gt+1, hi);
        assert isSorted(a, lo, hi);
    }

 

上面代码使用三个指针 lt gt i (less than , greater than)

其中 lt 指向的是比pivot小的那些数的下一个坐标, gt 指向的是比pivot大的那些数的上一个坐标。中间的就是跟pivot一样大的数了。

如若还不熟,建议用张纸,多画一画就好。

 

posted on 2014-04-08 13:52  Allen Blue  阅读(265)  评论(0编辑  收藏  举报

导航