Does the C++ standard library have a set ordered by insertion order?

前端 未结 6 354
春和景丽
春和景丽 2021-01-11 09:30

Does the C++ standard library have an \"ordered set\" datastructure? By ordered set, I mean something that is exactly the same as the ordinary std::set but that

相关标签:
6条回答
  • 2021-01-11 10:04

    No, it does not.

    Such a container presumably would need two different iterators, one to iterate in the order defined by the order of adding, and another to iterate in the usual set order. There's nothing of that kind in the standard libraries.

    One option to simulate it is to have a set of some type that contains an intrusive linked list node in addition to the actual data you care about. After adding an element to the set, append it to the linked list. Before removing an element from the set, remove it from the linked list. This is guaranteed to be OK, since pointers to set elements aren't invalidated by any operation other than removing that element.

    0 讨论(0)
  • 2021-01-11 10:10

    No single, homogeneous data structure will have this property, since it is either sequential (i.e. elements are arranged in insertion order) or associative (elements are arranged in some order depending on value).

    The best, clean approach would perhaps be something like Boost.MultiIndex, which allows you to add multiple indexes, or "views", on a container, so you can have a sequential and an ordered index.

    0 讨论(0)
  • 2021-01-11 10:11

    I thought the answer is fairly simple, combine set with another iteratable structure (say, queue). If you like to iterate the set in the order that the element been inserted, push the elements in queue first, do your work on the front element, then pop out, put into set.

    0 讨论(0)
  • 2021-01-11 10:12

    [Disclaimer: I have given a similar answer to this question already]

    If you can use Boost, a very straightforward solution is to use the header-only library Boost.Bimap (bidirectional maps).

    Consider the following sample program that will display some dummy entries in insertion order (try out here):

    #include <iostream>
    #include <string>
    #include <type_traits>
    #include <boost/bimap.hpp>
    
    using namespace std::string_literals;
    
    template <typename T>
    void insertByOrder(boost::bimap<T, size_t>& mymap, const T& element) {
      using pos = typename std::remove_reference<decltype(mymap)>::type::value_type;
      // We use size() as index, therefore indexing the elements with 0, 1, ...
      mymap.insert(pos(element, mymap.size()));
    }
    
    int main() {
      boost::bimap<std::string, size_t> mymap;
    
      insertByOrder(mymap, "stack"s);
      insertByOrder(mymap, "overflow"s);
    
      // Iterate over right map view (integers) in sorted order
      for (const auto& rit : mymap.right) {
        std::cout << rit.first << " -> " << rit.second << std::endl;
      }
    }
    

    The funky type alias in insertByOrder() is needed to insert elements into a boost::bimap in the following line (see referenced documentation).

    0 讨论(0)
  • 2021-01-11 10:14

    Yes, it's called a vector or list (or array). Just appends to the vector to add element to the set.

    0 讨论(0)
  • 2021-01-11 10:22

    Instead of making a std::set of whatever type you're using, why not pass it a std::pair of the object and an index that gets incremented at each insertion?

    0 讨论(0)
提交回复
热议问题