法一:只用一个模板参数
当比较自定义类型时,再重载自定义类型的<运算符
#include <iostream>
#include <vector>
#include <math.h>
using std::cout;
using std::endl;
using std::vector;
template<typename T>
class MyQsort
{
public:
MyQsort(T *arr, size_t size)//, Compare com
:_vec(arr,arr+size)
{
}
void quick(int left, int right);//, Compare &com
int partition(int left, int right);//, Compare &com
void print();
private:
vector<T> _vec;
};
template<typename T>
void MyQsort<T>::quick(int left, int right)
{
if(left<right)
{
//split左边的元素<_vec[split],右边的元素>_vec[split]
int split=partition(left,right);
quick(left,split-1);//对split左边的元素进行排序
quick(split+1,right);//对split右边的元素进行排序
}
}
template<typename T>
int MyQsort<T>::partition(int left, int right)
{
T tem=_vec[left];
int i=left;
int j=right;
while(i<j)
{
while(tem<_vec[j]&&i<j)
{
j--;
}
if(i<j)
{
_vec[i]=_vec[j];
i++;
}
while(_vec[i]<tem&&i<j)
{
i++;
}
if(i<j)
{
_vec[j]=_vec[i];
j--;
}
}
_vec[i]=tem;
return i;
}
template<typename T>
void MyQsort<T>::print()
{
for(auto &elem:_vec)
{
cout<<elem<<" ";
}
cout<<endl;
}
class Point
{
public:
Point()
:_x(0)
,_y(0)
{
}
Point(int x,int y)
:_x(x)
,_y(y)
{
}
float getDistance() const
{
return hypot(_x, _y);
}
private:
int _x;
int _y;
friend bool operator<(const Point &lhs,const Point &rhs);
friend std::ostream &operator<<(std::ostream &os,const Point &rhs);
};
bool operator<(const Point &lhs,const Point &rhs)
{
if(lhs.getDistance() < rhs.getDistance())
{
return true;
}
else if(lhs.getDistance() == rhs.getDistance())
{
if(lhs._x < rhs._x)
{
return true;
}
else if(lhs._x == rhs._x)
{
if(lhs._y < rhs._y)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
else
{
return false;
}
}
std::ostream &operator<<(std::ostream &os,const Point &rhs)
{
os<<"("<<rhs._x<<","<<rhs._y<<")";
return os;
}
void test()
{
int a[5]={4,1,1,65,3};
MyQsort<int>mq(a,5);
mq.quick(0,4);
mq.print();
Point pt[5]={Point(2,1),Point(1,1),Point(4,1),Point(3,1),Point(5,5)};
MyQsort<Point>mp(pt,5);
mp.quick(0,4);
mp.print();
}
int main()
{
test();
return 0;
}
法二:用到两个模板参数(第一个模板参数是类型,第二个模板参数制定了使用此参数时会进行什么操作)
#include <iostream>
#include <vector>
#include <math.h>
using std::cout;
using std::endl;
using std::vector;
template<typename T , typename Compare = std::less<T>>//Compare默认参数是std::less,std::less是std库里的类,此类默认实现的是内置类型的<比较
class MyQsort
{
public:
MyQsort(T *arr , size_t size)//, Compare com
:_vec(arr , arr + size)
{
}
void quick(int left , int right);//, Compare &com
int partition(int left , int right);//, Compare &com
void print();
private:
vector<T> _vec;
};
template<typename T , typename Compare>
void MyQsort<T , Compare>::quick(int left , int right)
{
if (left < right)
{
//split左边的元素<_vec[split],右边的元素>_vec[split]
int split = partition(left , right);
quick(left , split - 1);//对split左边的元素进行排序
quick(split + 1 , right);//对split右边的元素进行排序
}
}
template<typename T , typename Compare>
int MyQsort<T , Compare>::partition(int left , int right)
{
T tem = _vec[left];
int i = left;
int j = right;
Compare com;
while (i < j)
{
while (com(tem , _vec[j]) && i < j) //等价于:com.operator()(tem , _vec[j])
{
j--;
}
if (i < j)
{
_vec[i] = _vec[j];
i++;
}
while (com(_vec[i] , tem) && i < j)
{
i++;
}
if (i < j)
{
_vec[j] = _vec[i];
j--;
}
}
_vec[i] = tem;
return i;
}
template<typename T , typename Compare>
void MyQsort<T , Compare>::print()
{
for (auto &elem : _vec)
{
cout << elem << " ";
}
cout << endl;
}
struct MyCompare;//类的前向声明
class Point
{
public:
Point()
:_x(0)
, _y(0)
{
}
Point(int x , int y)
:_x(x)
, _y(y)
{
}
float getDistance() const
{
return hypot(_x , _y);
}
private:
int _x;
int _y;
friend std::ostream &operator<<(std::ostream &os , const Point &rhs);
friend struct MyCompare;
};
struct MyCompare //模板的第二个参数:自定义函数对象
{
//自己实现std::less<Point>的功能
bool operator()(const Point &lhs , const Point &rhs)
{
if (lhs.getDistance() < rhs.getDistance())
{
return true;
}
else if (lhs.getDistance() == rhs.getDistance())
{
if (lhs._x < rhs._x)
{
return true;
}
else if (lhs._x == rhs._x)
{
if (lhs._y < rhs._y)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
else
{
return false;
}
}
};
std::ostream &operator<<(std::ostream &os , const Point &rhs)
{
os << "(" << rhs._x << "," << rhs._y << ")";
return os;
}
namespace std //std库
{
template <>
//模板第二个参数默认是std::less
//未做特化前,std::less只能用于内置类型
//在std空间里做了针对Point的特化,使std::less也可用于自定义类型Point
struct less<Point>
{
bool operator()(const Point &lhs , const Point &rhs)
{
if (lhs.getDistance() < rhs.getDistance())
{
return true;
}
else //这里偷懒少写了一些比较情况
{
return false;
}
}
};
};
void test()
{
int a[5] = { 4,1,1,65,3 };
MyQsort<int>mq(a , 5);
mq.quick(0 , 4);
mq.print();
Point pt[5] = { Point(2,1),Point(1,1),Point(4,1),Point(3,1),Point(5,5) };
MyQsort<Point , MyCompare> mp(pt , 5);//用自定义的MyCompare实现Point的<比较
mp.print();
mp.quick(0 , 4);
mp.print();
MyQsort<Point> mp2(pt , 5); //用特化的std::less<Point>实现Point的<比较
//std::less<Point>是默认参数
//等价于MyQsort<Point,std::less<Point>> mp2(pt , 5);
mp2.quick(0 , 4);
mp2.print();
}
int main()
{
test();
return 0;
}