從快速排序開始的代碼演化

來源:互聯網
上載者:User

標籤:

note: 本文不討論快速排序的最佳化。

最近在溫習演算法。正好看到快速排序。

通過3個版本的改進,慢慢加入了template技能。這應該也算是一個收穫。

第一個版本:測試正確性。

通過比較int的數組排序。

 

int doSort(int* collection, int left, int right){    int    newRight;    if (left < right)     {        newRight = doPartition(collection,  left, right);        doSort(collection, left, newRight);        doSort(collection, newRight + 1, right);    }    return 0;}bool FindMidValue( int& exA, int& exB, int& exC,int& result){    if(exA>exB)    {        if(exB>exC)        {            result = exB;            return true;        }        if(exA>exC)        {            result = exC;            return true;        }        result = exA;        return true;    }    return false;}void doQueryMidValue(int* collection,int example1,int example2,int example3,int& result){    int& exA = collection[example1];    int& exB = collection[example2];    int& exC = collection[example3];    if(FindMidValue(exA,exB,exC,result)) return;     if(FindMidValue(exA,exC,exB,result)) return;    if(FindMidValue(exB,exA,exC,result)) return;    if(FindMidValue(exB,exC,exA,result)) return;     if(FindMidValue(exC,exA,exB,result)) return;    if(FindMidValue(exC,exB,exA,result)) return;            result = exA;}int doPartition(int* collection,int left, int right) {    int   cmpValue ;    int example1 = (rand() % (right - left + 1)) + left;    int example2 =(rand() % (right - left + 1)) + left;    int example3 = (rand() % (right - left + 1)) + left;            doQueryMidValue(collection,example1,example2,example3,cmpValue);    left--;    right++;    while (1)     {        do         {            right--;        } while (collection[right] > cmpValue);                   do         {            left++;        }while (collection[left] < cmpValue);                   if (left >= right)        {                  break;        }        else         {            int nTemp = collection[left];            collection[left] = collection[right];            collection[right] = nTemp;        }    }        return right;}

  第二個版本:支援泛型。

如果我要支援string,不能再寫一個版本,所以第二版解決資料類型變化的問題。

同時使用vector代替原始數組。

#include "stdafx.h"#include <xstddef>#include <algorithm>#include <vector>#include <stdlib.h>namespace BSP{    template<class T>    class QuickSort    {                public:        int Sort(std::vector< T >& collection);    private:        int doSort(std::vector< T >& collection,int left, int right);          int doPartition(std::vector< T >& collection,int left, int right);                void doQueryMidValue(std::vector< T >& collection,int example1,int example2,int example3,T& result);        bool FindMidValue( T& exA, T& exB, T& exC,T& result);        };    template<class T>    int QuickSort<T>::Sort(std::vector<T>& collection)    {            return doSort(collection,0,collection.size()-1);    }    template<class T>    int QuickSort<T>::doSort(std::vector<T>& collection,int left, int right)    {        int    newRight;        if (left < right)         {            newRight = doPartition(collection,  left, right);            doSort(collection, left, newRight);            doSort(collection, newRight + 1, right);        }        return 0;    }    template<class T>    bool QuickSort<T>::FindMidValue( T& exA, T& exB, T& exC,T& result)    {        if(exA>exB)        {            if(exB>exC)            {                result = exB;                return true;            }            if(exA>exC)            {                result = exC;                return true;            }            result = exA;            return true;        }        return false;    }    template<class T>    void QuickSort<T>::doQueryMidValue(std::vector< T >& collection,int example1,int example2,int example3,T& result)    {        T& exA = collection[example1];        T& exB = collection[example2];        T& exC = collection[example3];        if(FindMidValue(exA,exB,exC,result)) return;         if(FindMidValue(exA,exC,exB,result)) return;        if(FindMidValue(exB,exA,exC,result)) return;        if(FindMidValue(exB,exC,exA,result)) return;         if(FindMidValue(exC,exA,exB,result)) return;        if(FindMidValue(exC,exB,exA,result)) return;                result = exA;    }    template<class T>    int QuickSort<T>::doPartition(std::vector<T>& collection,int left, int right)     {        T   cmpValue ;        int example1 = (rand() % (right - left + 1)) + left;        int example2 =(rand() % (right - left + 1)) + left;        int example3 = (rand() % (right - left + 1)) + left;                doQueryMidValue(collection,example1,example2,example3,cmpValue);        left--;        right++;        while (1)         {            do             {                right--;            } while (m_pfnGreater(collection[right] , cmpValue));                       do             {                left++;            }while (m_pfnLess(collection[left] , cmpValue));                       if (left >= right)            {                      break;            }            else             {                std::swap(collection[left],collection[right]);                        }        }            return right;    }}

  第二個版本b:支援自訂的結構。

基礎類型int,stl的類型string都內建比較函數。所以可以直接比較。

但自訂的類型,編譯器就無法識別了。

第二個版本不動,自訂的結構需要重載operator 。

typedef struct Student{    std::string name;    int         year;          bool operator > (const struct Student& dst) const    {        printf("ref greater \n");        return this->year > dst.year;    }    bool operator < (const struct Student& dst) const    {        printf("ref less \n");        return this->year < dst.year;    }} Student;

  第三個版本:支援shared_Ptr。

之前的版本需要存放實體,這個對於效能有很大影響。

於是引入了shared_ptr。但這時比較函數進行的是shared_ptr的比較,並不是實際對象的比較。

所以需要增加自訂的比較函數。

首先需要提供預設的比較函數對象。這樣預設類型就不用強制設定了。

 template<class T        ,class _qsLess = std::less<T> 
        ,class _qsGreater = std::greater<T>
>    class QuickSort    {    public:        explicit QuickSort<T,_qsLess,_qsGreater>()        {            m_pfnLess = _qsLess();            m_pfnGreater = _qsGreater();        }           public:        int Sort(std::vector< T >& collection);    private:        int doSort(std::vector< T >& collection,int left, int right);          int doPartition(std::vector< T >& collection,int left, int right);                void doQueryMidValue(std::vector< T >& collection,int example1,int example2,int example3,T& result);        bool FindMidValue( T& exA, T& exB, T& exC,T& result);    private:        _qsLess    m_pfnLess;        _qsGreater  m_pfnGreater;    };    template<class T,class _qsLess ,class _qsGreater>    int QuickSort<T,_qsLess,_qsGreater>::Sort(std::vector<T>& collection)    {            return doSort(collection,0,collection.size()-1);    }    template<class T,class _qsLess ,class _qsGreater>    int QuickSort<T,_qsLess,_qsGreater>::doSort(std::vector<T>& collection,int left, int right)    {        int    newRight;        if (left < right)         {            newRight = doPartition(collection,  left, right);            doSort(collection, left, newRight);            doSort(collection, newRight + 1, right);        }        return 0;    }    template<class T,class _qsLess ,class _qsGreater>    bool QuickSort<T,_qsLess,_qsGreater>::FindMidValue( T& exA, T& exB, T& exC,T& result)    {        if(m_pfnGreater(exA,exB))        {            if(m_pfnGreater(exB,exC))            {                result = exB;                return true;            }            if(m_pfnGreater(exA,exC))            {                result = exC;                return true;            }            result = exA;            return true;        }        return false;    }    template<class T,class _qsLess ,class _qsGreater>    void QuickSort<T,_qsLess,_qsGreater>::doQueryMidValue(std::vector< T >& collection,int example1,int example2,int example3,T& result)    {        T& exA = collection[example1];        T& exB = collection[example2];        T& exC = collection[example3];        if(FindMidValue(exA,exB,exC,result)) return;         if(FindMidValue(exA,exC,exB,result)) return;        if(FindMidValue(exB,exA,exC,result)) return;        if(FindMidValue(exB,exC,exA,result)) return;         if(FindMidValue(exC,exA,exB,result)) return;        if(FindMidValue(exC,exB,exA,result)) return;                result = exA;    }    template<class T,class _qsLess ,class _qsGreater>    int QuickSort<T,_qsLess,_qsGreater>::doPartition(std::vector<T>& collection,int left, int right)     {        T   cmpValue ;        int example1 = (rand() % (right - left + 1)) + left;        int example2 =(rand() % (right - left + 1)) + left;        int example3 = (rand() % (right - left + 1)) + left;                doQueryMidValue(collection,example1,example2,example3,cmpValue);                left--;        right++;        while (1)         {            do             {                right--;            }while (m_pfnGreater(collection[right] , cmpValue));

            do             {                left++;            }while (m_pfnLess(collection[left] , cmpValue));

                       if (left >= right)            {                      break;            }            else             {                std::swap(collection[left],collection[right]);                        }        }            return right;    }

  

 對於使用者,需要增加比較函數的實現。 


struct StudentPtrLess:public std::binary_function<StudentPtr, StudentPtr, bool> { bool operator () ( StudentPtr& src, StudentPtr& dst) { if(src == false) return true; if(dst == false) return false; return *(src.get()) < *(dst.get()); } }; struct StudentPtrGreater:public std::binary_function<StudentPtr, StudentPtr, bool> { bool operator () ( StudentPtr& src, StudentPtr& dst) { if(src == false) return false; if(dst == false) return true; return *(src.get()) > *(dst.get()); } }; BSP::QuickSort< StudentPtr ,StudentPtrLess , StudentPtrGreater> qsStudentPtr;

  


 

從快速排序開始的代碼演化

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.