C ++如何使用Template对Vector进行排序

时间:2012-11-16 08:34:39

标签: c++ templates sorting vector

C ++如何使用模板对矢量进行排序

嗨,大家好,感谢您查看我的问题。

我有一个这样的Templates.h文件..

/* Template Less Than */

template<typename T>
bool lessThan(T a,T b)
{
return a<b;
}

/* Template greater Than */

template<typename T>
bool greaterThan(T a,T b)
{
return a>b;
}

/* Template Equals */

template<typename T>
bool equals(T a,T b)
{
return a==b;
}

然后我得到了这个课程

Map2D

关于Map2D ..

class Map2D
{
protected:
int x;
int y;

public:
Map2D();
Map2D(int,int);
int getX();
int getY();
};

在我的main.cpp中,我得到了一个Map2D的矢量类

vector<Map2D> map2d;

所以现在我需要通过X升序对它进行排序..我如何利用模板文件对它的向量进行排序X升序..考虑我以后需要重载​​另一个用于DESCENDING ...

通常我会用

sort(map2d.begin(),map2d.end(),sortByX);

和sortByX将是一个由it()运算符重载的结构。

但现在的问题是,因为我得到的模板小于和大于..我如何利用它来升序排序X,然后通过模板通用函数Template.H降序来排序另一个X.

更新

我想我需要重载类Map2D运算符&gt; ,&lt;和==

但我的问题是如何在MyTemplates.h函数的帮助下重载它,例如lessserThan,greaterThan,equals

感谢。

8 个答案:

答案 0 :(得分:5)

为您的班级定义比较器或更简单,operator<()重载(无论如何您需要为模板工作)。

首先,修复模板:

template<typename T>
bool lessThan(const T& a, const T& b)
{
    return a<b;
}

template<typename T>
bool greaterThan(const T& a, const T& b)
{
    return b<a;
}

template<typename T>
bool equals(const T& a, const T& b)
{
    return !(a<b || b<a);
}

接下来,在您的班级上定义一个运算符&lt;()。

class Map2D
{
protected:
    int x;
    int y;

public:
    Map2D();
    Map2D(int,int);
    int getX();
    int getY();

    // this sample sorts on X dominantly, and Y if X is the same
    bool operator <(const Map2D& obj) const
    {
        return (x < obj.x || (x == obj.x && y < obj.y));
    };
}

现在只需调用sort:

std::sort(map2d.begin(), map2d.end());

使用您的lessThan模板调用:

std::sort(map2d.begin(), map2d.end(), lessThan<Map2D>);

或者你的更大的模板:

std::sort(map2d.begin(), map2d.end(), greaterThan<Map2D>);

答案 1 :(得分:4)

在C ++ 11中,您可以编写一个lambda函数来执行此操作。

使用boost,如果你想要一个“一步一步”的仿函数,它必须是这样的:

bind( less<int>, bind(&Map2D::getX(),_1), bind(&Map2D::getX(),_2) )
// or your lessThan<int> which already exists in C++ as less<int>

不确定这是否可行。 (第二和第三种绑定是否会正确转换为占位符?)更容易编写一个非常通用的函子,它结合了你想要做的事情,即从你的类中提取一些东西(一个转换)然后将它传递给谓词。

template< typename Trans, typename Pred >
struct Comparator
{
    Comparator( Trans t , Pred p ) : trans( t ), pred ( p )
    {
    }

    template< typename T >
    bool operator()( T const& t1, T const& t2 ) const
    {
         return pred( trans(t1), trans(t2) );
    }
private:
    Trans trans;
    Pred pred;
};


template< typename Trans, typename Pred >
Comparator< Trans, Pred > makeComparator( Trans t, Pred p )
{
     return Comparator( t, p );
}

// then in your code

std::sort( map2d.begin(), map2d.end(), 
    makeComparator( boost::bind( &Map2D::getX(), _1 ), lessThan<int> ) );

应该可以工作,并且你保持比较器的通用性。

(不确定是否已经提供类似的东西)。

答案 2 :(得分:4)

您的代码存在一些问题:

  1. 课程最后缺少分号。
  2. 您的比较模板应返回bool而不是T
  3. 您错过了班级中的比较运算符:

    bool operator<(const Map2D &m) const {return /* some code here */ }
    bool operator>(const Map2D &m) const {return /* some code here */ }
    bool operator==(const Map2D &m) const {return /* some code here */ }
    

    或修改您的模板仅使用operator<()进行所有比较(这是BTW的常见做法)。

  4. 当您修复上述内容时,您只需使用以下模板:

    sort(map2d.begin(),map2d.end(), lessThan<Map2D>);
    sort(map2d.begin(),map2d.end(), greaterThan<Map2D>);
    
    顺便说一句,您不需要自定义模板就可以轻松地对课程进行排序。重用STL中已有的内容:

    sort(map2d.begin(),map2d.end()); // less
    sort(map2d.begin(),map2d.end(), std::greater<Map2D>());
    

    您可以在functional标题中找到这些内容。您也不能使用operator==()进行排序,但它可能对C ++ 11中引入的unordered containers有用。

    编辑:如果你的Map2D类的排序算法是固定的(那么不会随着时间的推移而改变),而不是我建议的回答。否则,如果现在你想按X排序,经过几行Y而不是@MikeSeymour回答可能更适合你的需要。

答案 3 :(得分:2)

如果您使用的是C ++ 11,则可以编写如下内容:

std::sort(map2d.begin(), map2d.end(), [](const Map2D& a, const Map2D& b) {
    return lessThan(a.getX(), b.getX()); } ); // accending
std::sort(map2d.begin(), map2d.end(), [](const Map2D& a, const Map2D& b) {
    return greaterThan(a.getX(), b.getX()); }); // decending

否则你必须实现比较仿函数,即

struct compare
{
    bool operator () (const Map2D& a, const Map2D& b)
    {
        return lessThan(a.getX(), b.getX());
    }
};

然后

std::sort(map2d.begin(), map2d.end(), compare());

但是真的不是一个好的风格,因为你可以直接比较x,而不是更好。如果你想对Map2D进行一些特殊的比较,那么最好只为Map2D对象制作这些比较函数。

Upd:您也可以只使用函数指针作为比较器,即:

bool compare(const Map2D& a, const Map2D& b)
{
    return lessThan(a.getX(), b.getX());
}

然后

std::sort(m.begin(), m.end(), compare);

但是你可能会失去一些表现(见下面的评论)。

答案 4 :(得分:1)

你不能真的。您需要定义仿函数(函数或适当重载operator()的类)来执行您需要的特定对象成员比较,并且您的函数模板不会这样做。你需要这样的东西:

struct compare_x_less {
    // NOTE: you'll need to declare `get_X() const` for this to work.
    // You should do that anyway.
    bool operator()(Map2D const & a, Map2D const & b) {
        return a.get_X() < b.get_X();
    }
};

// and similarly for `compare_x_greater` and any other comparisons you need

std::sort(map2d.begin(),map2d.end(),compare_x_less());

在C ++ 11中,lambdas可以节省一些输入:

std::sort(map2d.begin(),map2d.end(),[](Map2D const & a, Map2D const & b) {
        return a.get_X() < b.get_X();
    });

答案 5 :(得分:1)

首先需要重载运算符<>==以将Map2D与模板一起使用:

class Map2D
{
protected:
   int x;
   int y;
public:
   Map2D();
   Map2D(int,int);
   int getX();
   int getY();
   bool operator<(const Map2D& other)const //less then
   {
      return x < other.x;
   }
   //other operators is same manner
}

完成后你就可以使用它了:

sort(map2d.begin(),map2d.end(),lessThan<Map2D>);

答案 6 :(得分:0)

sort(map2d.begin(),map2d.end(),lessThan<map2d>);

请注意小于谓词函数应该返回而不是类型bool的T值

一些额外的解释:

// usage
    /* Some moments to mention: if you omit third argument, default argument less<T> will be used,
    which is enough for built-in types, also you can use predicates already defined in STL:
    greater<T>, less<T> or you can provide your own predicate */
    sort(map2d.begin(),map2d.end(),lessThan<map2d>);

// header file, where we define predicats which we shall provide as argument to algorithm sort

// predicate expected by function sort has to obey the following rules:
// 1. return bool 2. accept 2 parameters

/*2 variants of predicat*/

// 1) operator< is overloaded for class T, so we can use it to compare instances of that class
template<typename T>
bool lessThan(T a,T b)
{
return a < b;
}

/* 2) operator< not overloaded, when we have to get values of class members by which we are going to compare them
this could be done in various ways, for ex. by means of getters();*/

template<typename T>
bool lessThan(T a,T b)
{
return a.getValueOfMember() < b.getValueOfMember();
}

答案 7 :(得分:0)

一个好方法,我认为它不是最好的。 您可以重载操作员(&lt;)&amp; (!=)在课堂上。如果你只想排序X. 只需使用sort(map2d.begin(), map2d.end())进行升序即可。和sort(map2d.rbegin(), map2d.rend())下降..这解决了你的问题。

OR: 您可以使用2个函数来比较1与x&amp;另一个与Y有关。 为:

int cmpx(const void* A, const void *B){
    Map2D a = *(Map2D *)A;
    Map2D b = *(Map2D *)B;
    if(a.x < b.x) return -1;
    if(a.x == b.x) return 0;
    return 1;
}
// And use
qsort(map2d.begin(), (int)map2d.size(), sizeof(Map2D), cmpx);

对于Y. 不确定map2d.rbegin()是否会对此进行降序排序,或者您也必须自己进行排序。