【问题标题】:I want use set to remove duplicate element and keep the order when they insert我想使用 set 删除重复元素并在插入时保持顺序
【发布时间】:2015-05-23 23:44:46
【问题描述】:

我想使用 set 删除重复元素并同时保持它们的顺序。所以我尝试更改比较参数,让它们按照插入的顺序进行排序。

#include <set>
#include <iostream>
using namespace std;


template <class T>
struct compare
{
    bool operator() (T x, T y) 
    {
        return true;
    }
};

void main()
{
    set<int,compare<int>> one;

    one.insert(5);
    one.insert(3);
    one.insert(9);
    one.insert(1);
    one.insert(5);
    one.insert(5);
}

IDE 的表达式是 :invaild operator

【问题讨论】:

  • A std::set 已经订购了它的商品并且不包含重复商品。您无需“帮助”解决任何这些问题。所以我猜set 不是你应该使用的容器。
  • 您是否有理由要使用 std::set? 你想做什么?
  • 我知道它里面没有重复项。我只想按照插入的顺序放置所有元素。
  • 例如,"5,3,6,7,1" 已被一一插入,我希望它们仍然保持相同的顺序,,"5,3,6,7, 1",插入该集合后。
  • std::set 需要一个简单的弱排序。插入顺序不满足这一点。你的比较器肯定不会。

标签: c++ stl set


【解决方案1】:

std::set 依靠比较器来保持严格的弱排序并确保每个值都是唯一的。您不能按照插入顺序对std::set 进行排序。

一种可能的解决方案是使用两个容器,一个 std::set 包含唯一元素,一个 std::vector 索引来保持它们被插入的顺序。向量可能包含指向集合的迭代器。

使用自己的迭代器将这两个容器封装在您自己的类中可能会很方便。这是一个简单的实现:

class MySetIterator {
  std::vector<std::set<int>::iterator>::iterator pos;
public:
  MySetIterator(std::vector<std::set<int>::iterator>::iterator pos) : pos(pos) {}
  int operator*() { return **pos; }
  MySetIterator& operator++() { ++pos; return *this; }
  bool operator!=(const MySetIterator& rhs) { return pos != rhs.pos; }    
};

class MySet {
 std::set<int> vals;
 std::vector<std::set<int>::iterator> order;
public:
  void insert(int val) { 
    auto ret = vals.insert(val);
    if (ret.second)
      order.push_back(ret.first);
  }
  MySetIterator begin() { return {order.begin()}; }
  MySetIterator end() { return {order.end()}; }    
};

int main() {
  MySet my_set;

  my_set.insert(5);
  my_set.insert(3);
  my_set.insert(9);
  my_set.insert(1);
  my_set.insert(5);
  my_set.insert(5);
  for (int val : my_set)
      std::cout << val << " ";
}

【讨论】:

    【解决方案2】:

    其他可能的解决方案是使用 boost::multi_index。

    #include <iostream>
    
    #include <boost/multi_index_container.hpp>
    #include <boost/multi_index/ordered_index.hpp>
    #include <boost/multi_index/random_access_index.hpp>
    
    namespace boost_mi = boost::multi_index;
    
    typedef boost::multi_index_container<
        int,
        boost_mi::indexed_by<
            boost_mi::random_access<>, // preserves insertion order
            boost_mi::ordered_unique<boost_mi::identity<int> > // removes duplicates
        >
    > MySet;
    
    int main()
    {
        MySet my_set;
    
        my_set.push_back(5);
        my_set.push_back(3);
        my_set.push_back(9);
        my_set.push_back(1);
        my_set.push_back(5);
        my_set.push_back(5);
    
        for (auto val : my_set) {
            std::cout << val << std::endl;
        }
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-21
      • 1970-01-01
      • 2013-03-21
      • 1970-01-01
      • 2011-12-18
      • 2013-03-24
      • 1970-01-01
      相关资源
      最近更新 更多