zoukankan      html  css  js  c++  java
  • 再来看看快速排序

    #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一样大的数了。

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

  • 相关阅读:
    CGI(通用网关接口)
    PHP简介
    SEO搜索引擎优化/URL
    使用表单标签,与用户交互
    认识<img>标签,为网页插入图片
    使用mailto在网页中链接Email地址
    使用<a>标签,链接到另一个页面
    1037. Magic Coupon (25)
    1038. Recover the Smallest Number (30)
    1034. Head of a Gang (30) -string离散化 -map应用 -并查集
  • 原文地址:https://www.cnblogs.com/4everlove/p/3651839.html
Copyright © 2011-2022 走看看