簡體   English   中英

需要按插入順序設置 STL

[英]need STL set in insertion order

如何按插入順序在集合中存儲元素。 例如。

set<string>myset;

myset.insert("stack");
myset.insert("overflow");

如果打印,輸出是

overflow
stack

需要的輸出:

stack
overflow

一種方法是使用兩個容器,一個std::deque以插入順序存儲元素,另一個std::set以確保沒有重復項。

插入元素時,先檢查它是否在set ,如果是,則將其扔掉; 如果它不存在,請將其插入dequeset

一種常見的情況是先插入所有元素,然后進行處理(不再插入),如果是這種情況,則可以在插入處理后釋放set

set是保持插入順序的錯誤容器,它會根據排序標准對其元素進行排序並忘記插入順序。 為此,您必須使用排序容器,例如 vector、deque 或 list。 如果您還需要關聯訪問set ,則必須同時將元素存儲在多個容器中,或者使用非 STL 容器,如boost::multi_index ,它可以同時維護多個元素順序。

PS:如果您在將元素插入集合之前對元素進行排序,則集合會將它們按插入順序排列,但我認為這不會解決您的問題。

如果除了插入順序之外不需要任何順序,您還可以將插入編號存儲在存儲元素中並將其作為排序標准。 但是,為什么在這種情況下會使用 set 完全讓我無法理解。 ;)

這是我的方法:

template <class T>
class VectorSet
{
public:
  using iterator                     = typename vector<T>::iterator;
  using const_iterator               = typename vector<T>::const_iterator;
  iterator begin()                   { return theVector.begin(); }
  iterator end()                     { return theVector.end(); }
  const_iterator begin() const       { return theVector.begin(); }
  const_iterator end() const         { return theVector.end(); }
  const T& front() const             { return theVector.front(); }
  const T& back() const              { return theVector.back(); }
  void insert(const T& item)         { if (theSet.insert(item).second) theVector.push_back(item); }
  size_t count(const T& item) const  { return theSet.count(item); }
  bool empty() const                 { return theSet.empty(); }
  size_t size() const                { return theSet.size(); }
private:
  vector<T> theVector;
  set<T>    theSet;
};

當然,可以根據需要添加新的轉發功能,並且可以轉發到兩種數據結構中最有效地實現它們的任何一種。 如果您打算在這方面大量使用 STL 算法(到目前為止我還不需要),您可能還想定義 STL 期望找到的成員類型,如 value_type 等。

如果您可以使用 Boost,一個非常簡單的解決方案是使用僅標頭庫Boost.Bimap (雙向映射)。

考慮以下示例程序,它將按插入順序顯示您的虛擬條目(請在此處嘗試):

#include <iostream>
#include <string>
#include <type_traits>
#include <boost/bimap.hpp>

using namespace std::string_literals;

template <typename T>
void insertCallOrdered(boost::bimap<T, size_t>& mymap, const T& element) {
  // We use size() as index, therefore indexing with 0, 1, ... 
  // as we add elements to the bimap.
  mymap.insert({ element, mymap.size() });
}

int main() {
  boost::bimap<std::string, size_t> mymap;

  insertCallOrdered(mymap, "stack"s);
  insertCallOrdered(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;
  }
}

我只是想知道為什么沒有人建議使用像 Boost MultiIndex 這樣好的庫。 這是一個如何做到這一點的示例:

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/indexed_by.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/ordered_index.hpp>

#include <iostream>

template<typename T>
using my_set = boost::multi_index_container<
    T,
    boost::multi_index::indexed_by<
        boost::multi_index::sequenced<>,
        boost::multi_index::ordered_unique<boost::multi_index::identity<T>>
    >
>;

int main() {
    my_set<int> set;
    set.push_back(10);
    set.push_back(20);
    set.push_back(3);
    set.push_back(11);
    set.push_back(1);
    
    // Prints elements of the set in order of insertion.
    const auto &index = set.get<0>();
    for (const auto &item : index) {
        std::cout << item << " ";
    }

    // Prints elements of the set in order of value.
    std::cout << "\n";
    const auto &ordered_index = set.get<1>();
    for (const auto &item : ordered_index) {
        std::cout << item << " ";
    }
}

你需要的是這個,非常簡單的標准庫。 示例在線編譯器鏈接: http : //cpp.sh/7hsxo

#include <iostream>
#include <string>
#include <unordered_set> 
static std::unordered_set<std::string> myset;


int main()
{
    myset.insert("blah");
    myset.insert("blah2");
    myset.insert("blah3");

    int count = 0;
    for ( auto local_it = myset.begin(); local_it!= myset.end(); ++local_it ) {
          printf("index: [%d]: %s\n", count,  (*local_it).c_str());
          count++;
    }
    printf("\n");
    for ( unsigned i = 0; i < myset.bucket_count(); ++i) {
        for ( auto local_it = myset.begin(i); local_it!= myset.end(i); ++local_it )
              printf("bucket: [%d]: %s\n", i,  (*local_it).c_str());
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM