码迷,mamicode.com
首页 > 编程语言 > 详细

从快速排序开始的代码演化

时间:2015-04-13 14:14:41      阅读:182      评论:0      收藏:0      [点我收藏+]

标签:

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;

  

从快速排序开始的代码演化

标签:

原文地址:http://www.cnblogs.com/febwave/p/4421792.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!