[英]need STL set in insertion order
如何按插入順序在集合中存儲元素。 例如。
set<string>myset;
myset.insert("stack");
myset.insert("overflow");
如果打印,輸出是
overflow
stack
需要的輸出:
stack
overflow
一種方法是使用兩個容器,一個std::deque
以插入順序存儲元素,另一個std::set
以確保沒有重復項。
插入元素時,先檢查它是否在set
,如果是,則將其扔掉; 如果它不存在,請將其插入deque
和set
。
一種常見的情況是先插入所有元素,然后進行處理(不再插入),如果是這種情況,則可以在插入處理后釋放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.