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