【问题标题】:Sorting Sets using std::sort使用 std::sort 对集合进行排序
【发布时间】:2012-11-03 08:01:23
【问题描述】:

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

set container 好像没有排序功能。我被建议使用矢量。 但是集合只能存储独特的元素。

Q1:如何根据条件对集合进行排序

Q2:如果 set 无法做到这一点,那么哪个 STL 容器是最佳选择,我如何对容器中的元素进行排序。

【问题讨论】:

    标签: c++ stl set


    【解决方案1】:

    您可以拥有两组并保持同步或将一组复制到另一组。

    #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;
    }
    

    程序返回: 由A 1,8 2,7 3,6

    作者: 3,6 2,7 1,8

    【讨论】:

      【解决方案2】:

      您不能使用set,它的排序方式是特定set 类型的一部分。给定的set 具有无法更改的固定设置顺序。

      您可以相对轻松地使用相同的数据创建一个新的set。只需创建一个新的set,它会根据新标准进行排序。

      如果您想在同一代码中使用两个set,则必须抽象出对底层set 的访问。

      现在,如果您很少进行读取和修改,使用手动排序的vector 通常是一个更好的主意。您可以使用 std::unique-erase 成语删除重复项。

      【讨论】:

      • Vector 对我来说没问题。但我不确定如何实现 std::unique-erase 。你能建议吗?
      • @user1571494:给定一个已排序的向量,v.erase(std::unique(v.begin(), v.end()), v.end()); 将删除重复项。
      • 请注意,@Mike 编写的上述代码将使用operator== 来比较它们。你可能需要传入一个谓词,这样你就只需要对排序等效的东西进行核对(!(a&lt;b) &amp;&amp; !(b&lt;a))
      • 还要注意不要错过最后一个, v.end()——它会编译,但不会做任何明智的事情,但可能会通过一些手动测试。
      【解决方案3】:

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

      如果您不喜欢默认的排序标准,您可以向std::set&lt;&gt; 提供第二个模板参数

      【讨论】:

      • 是的……我明白了。但我可以重新排序吗
      • @user1571494 - 不,您不能重新排序。您可以将项目从 std::set&lt;&gt; 复制到不同的容器中 - 可能是具有不同比较模板参数的 std::set
      • 我相信集合接受一个比较器,或一个对象(指向函数的指针或具有函数调用运算符的类),它能够在集合中获取 2 个对象并确定绝对顺序它们之间。如果您查看此页面底部的示例:cplusplus.com/reference/stl/set/set,则有一个带有自定义比较器的集合示例。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多