标签:
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