使用std::sort排序集合

16

我想知道是否可以对预先创建的集合进行排序。当我首次创建集合s_p2时,我使用不同的元素point.getLength()进行了排序,但是在用户输入后,我想根据x值point.getX()对项进行排序。我该怎么做?

似乎set容器没有排序功能。建议使用vector。但是set只能存储唯一元素。

问题1:如何根据条件对set进行排序?

问题2:如果set无法实现排序,则哪种STL容器最好,并且如何对其中的元素进行排序。

3个回答

20

无法对set进行排序,因为排序方式是该特定set类型的一部分。给定的set具有固定的顺序,无法更改。

您可以相对容易地创建一个具有相同数据的新set。只需创建一个基于新标准排序的新set即可。

如果要在同一代码中使用两个set,则必须抽象访问底层set

现在,如果您进行的是罕见的读取和修改操作,则手动排序的vector通常是更好的选择。您可以通过使用std::unique-erase习惯用法来删除重复项。


向量对我来说没问题。但我不确定如何实现std::unique-erase。你能给些建议吗? - M.A
2
@user1571494:给定一个已排序的向量,v.erase(std::unique(v.begin(), v.end()), v.end());将删除重复项。 - Mike Seymour
3
请注意,@Mike编写的上述代码将使用operator==进行比较。你可能需要传递一个谓词(predicate),以便只消除那些在排序方面等价的内容(!(a<b) && !(b<a)) - Yakk - Adam Nevraumont
还要注意不要错过最后的, v.end() -- 它可以编译通过,但不会做任何有意义的事情,但可能会通过一些手动测试。 - Yakk - Adam Nevraumont

10

std::set以有序方式存储其成员。如果您从.begin().end()遍历集合,将得到一个排序后的项目列表。

如果您不喜欢默认的排序标准,则可以为std::set<>提供第二个模板参数。


是的,我明白。但我可以重新排序吗? - M.A
@user1571494 - 不,您无法重新排序它。您可以将std::set<>中的项目复制到不同的容器中,例如带有不同比较模板参数的std::set - Robᵩ
我相信集合可以接受一个比较器,或者一个对象(可以是指向函数的指针或者带有函数调用运算符的类),该对象能够取两个集合中的对象并确定它们之间的绝对顺序。如果您查看此页面底部的示例:http://www.cplusplus.com/reference/stl/set/set/,您会看到一个使用自定义比较器的集合示例。 - Wug

4

你可以拥有两个集合并使它们保持同步,或者复制一个集合到另一个集合。

#include <iostream>
#include <set>

using namespace std;

struct AB
{
   AB(int a,int b) : _a(a),_b(b) {}

   int _a;
   int _b;
};

struct byA
{
    bool operator () (const AB& lhs, const AB& rhs)
    {
          return lhs._a <= rhs._a;
    }
}; 

struct byB
{
    bool operator () (const AB& lhs, const AB& rhs)
    {
       return lhs._b <= rhs._b;
    }
}; 

typedef set<AB,byA> ByA;
typedef set<AB,byB> ByB;
typedef ByA::const_iterator ByAIt;
typedef ByB::const_iterator ByBIt;

void getByB(const ByA &sA,ByB &sB)
{
   for(ByAIt iter=sA.begin(); iter!=sA.end();++iter) {
      const AB &ab=*iter;
      sB.insert(ab);
   }
}

int main(int argc, const char **argv)
{
   ByA sA;
   sA.insert(AB(3,6));
   sA.insert(AB(1,8));
   sA.insert(AB(2,7));

   ByB sB;
   getByB(sA,sB);

   cout << "ByA:" << endl;
   for(ByAIt iter=sA.begin(); iter!=sA.end();++iter) {
      const AB &ab=*iter;
      cout << ab._a << "," << ab._b << " ";
   }
   cout << endl << endl;

   cout << "ByB:" << endl;
   for(ByBIt iter=sB.begin(); iter!=sB.end();++iter) {
      const AB &ab=*iter;
      cout << ab._a << "," << ab._b << " ";
   }
   cout << endl;
   return 0;
}

程序返回结果:

ByA: 1,8 2,7 3,6

ByB: 3,6 2,7 1,8


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接