C++ 选择具有唯一性且保持插入顺序的STL容器
我无法决定在以下情况下使用哪个STL容器:C++ 选择具有唯一性且保持插入顺序的STL容器,c++,stl,C++,Stl,我无法决定在以下情况下使用哪个STL容器: 我想保留元素的插入顺序 容器中的元素必须是唯一的 有没有现成的容器可以装这个?我不想在每次执行推回操作之前先使用向量,然后执行std::find。可能有一种很好的内置方法,但一种相当简单的方法是同时使用哈希映射和列表。在每次插入之前检查hash_映射,然后将其同时插入。您可能希望将其封装在一个类中。在您选择的容器(例如list、vector、deque)上实现一个包装类,并重写插入/推回方法,以在插入元素之前检查插入的元素是否唯一 不幸的是,我不知道任
有没有现成的容器可以装这个?我不想在每次执行
推回操作之前先使用向量,然后执行std::find
。可能有一种很好的内置方法,但一种相当简单的方法是同时使用哈希映射和列表。在每次插入之前检查hash_映射,然后将其同时插入。您可能希望将其封装在一个类中。在您选择的容器(例如list、vector、deque)上实现一个包装类,并重写插入/推回方法,以在插入元素之前检查插入的元素是否唯一
不幸的是,我不知道任何STL容器符合您的标准 没有标准的库容器直接提供您想要的内容。我将从一个std::vector开始,并编写一个免费函数来执行insert,它为您执行find和push_返回。如果这足够了,就不要再继续了。如果您有性能问题,请考虑一个更复杂的解决方案。应该能够完全满足您的要求-您只需使用一个顺序索引即可获得“按插入顺序排序”的要求,或者是一个hash_unique
或者是一个有序的_unique索引来获得唯一性要求。正如其他人所说,没有一个STL容器可以做到这一点。我喜欢尼尔·巴特沃斯的回答。另一种选择是同时使用集合和向量。转到“插入”时,请检查元素是否在集合中。如果是,则不能插入,因为这将违反您的唯一性要求。如果不是,则将其添加到集合中,然后将其插入向量中。这很容易实现,并且可以封装到单个类中。折衷是增加内存开销。但是你可以通过在单个向量上寻找你自己来换取增加的计算时间。这完全取决于您在问题域中处理的数据量以及您的时间和内存限制(如果有)。如果您已经安装了boost,我喜欢这个选项。否则,为什么不使用一个列表或向量并在插入时添加一个检查(find(k)==std::npos)
?我想在一个非常非常大的列表上,它可能会变得有点慢,但在大多数情况下,它会工作得很好。您可以这样做:
- 围绕元素类创建一个包含两个成员的包装器:元素和索引。我们称之为“插入-删除”。索引将是插入顺序
- 为此类定义比较运算符,它只考虑元素,而不考虑索引。这将确保元素的唯一性,同时记住它们的插入顺序
- 将std::set和插入计数器包装到另一个类中。然后,如果要插入新元素,请执行以下任一操作:
- 它已经存在,没有什么可做的
- 它不会:将其插入地图,同时为其指定当前最大索引+1李>
class CMagicContainer
{
public:
std::set<InsertedElement> collection;
int indexGenerator;
...
};
class CMagicContainer
{
公众:
std::集合集合;
int指数发生器;
...
};
嗯,我曾经有过类似的情况。我脑海中浮现的一件事是“我可以使用多个键吗?”?我在谷歌上搜索了一会儿,发现了一个使用std::set的示例。因此,如果您无法使用boost(我建议您使用它,重新发明车轮是没有意义的);你可以试试下面的例子。我认为您可以使用辅助键作为插入位置(自动递增)。从我在互联网上找到的例子;我根据自己的需要量身打造。这是一个相同的修改版本
卡瓦特:它正在使用宏。我知道它们总的来说是邪恶的,但我想这种用法是可以的
#include <set>
#include <functional>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>
#define MULTIKEYDEF(NAME,TYPE) \
inline TYPE const & NAME() const { return d_##NAME; } \
inline void NAME(TYPE const & t) { d_##NAME = t; } \
TYPE d_##NAME; \
class T##NAME \
: public std::unary_function<Tmultikey*,bool> { \
private: \
TYPE d_compare; \
public: \
T##NAME(TYPE t) : d_compare(t) {} \
T##NAME(T##NAME const & self) \
: d_compare(self.d_compare) {} \
bool operator()(Tmultikey * mk) { \
return d_compare == mk->##NAME(); \
} \
inline TYPE const& name() const { return d_compare; } \
}
class Tmultikey {
public:
// Actual keys
// Can be accessed through d_primary and d_secondary,
// or primary() and secondary()
MULTIKEYDEF(primary , std::string);
MULTIKEYDEF(secondary, unsigned int);
// Mandatory
bool operator < (Tmultikey const& mk) const {
if(primary() < mk.primary()) return true;
else if(primary() == mk.primary()) {
return secondary() < mk.secondary();
}
return false;
}
// Constructor
Tmultikey(std::string p, unsigned int s)
: d_primary(p), d_secondary(s) {}
// Eraser for std::set
template<typename Compare>
static void erase(std::set<Tmultikey> & c, Compare op) {
typename std::set<Tmultikey>::iterator pos = c.begin();
while(pos != c.end()) {
if(op(&(*pos))) {
c.erase(pos++);
} else ++pos;
}
}
// Eraser for std::set
template<typename Compare>
static std::set<Tmultikey>::iterator find_ex(std::set<Tmultikey> & c, Compare op) {
typename std::set<Tmultikey>::iterator pos = c.begin();
while(pos != c.end()) {
if(op(&(*pos))) {
break;
} else ++pos;
}
return pos;
}
};
int main(int argc, char* argv[])
{
std::set<Tmultikey> mkset;
mkset.insert(Tmultikey("1",5));
mkset.insert(Tmultikey("6",4));
mkset.insert(Tmultikey("3",7));
mkset.insert(Tmultikey("1",6));
std::set<Tmultikey>::iterator bg = mkset.begin();
for (;bg != mkset.end(); ++bg)
{
std::cout<<(*bg).primary()<<std::endl;
}
Tmultikey::erase(mkset,Tmultikey::Tsecondary(4));
//Tmultikey::erase(mkset,Tmultikey::Tprimary("1"));
std::cout<<"After erase ....\n";
bg = mkset.begin();
for (;bg != mkset.end(); ++bg)
{
std::cout<<(*bg).primary()<<std::endl;
}
bg = mkset.find(Tmultikey("3",7));
if (bg != mkset.end())
{
std::cout<<"Absolute Find:"<<(*bg).primary()<<" "<<(*bg).secondary()<<std::endl;
}
//bg = Tmultikey::find_ex(mkset,Tmultikey::Tprimary("1"));
bg = Tmultikey::find_ex(mkset,Tmultikey::Tsecondary(5));
if (bg != mkset.end())
{
std::cout<<"Partial Find:"<<(*bg).primary()<<" "<<(*bg).secondary()<<std::endl;
}
else {
std::cout<<"Partial Find: FAILED\n";
}
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#定义MULTIKEYDEF(名称、类型)\
内联类型const&NAME()const{return d###NAME;}\
内联void NAME(类型const&t){d##NAME=t;}\
键入d###名称\
类T##名称\
:public std::一元函数{\
私人:\
d_型比较\
公众:\
T##NAME(类型T):d#u compare(T){\
T##NAME(T##NAME const&self)\
:d_compare(self.d_compare){}\
布尔运算符()(Tmultikey*mk){\
返回d#u compare==mk->##NAME()\
} \
内联类型const&name()const{return d_compare;}\
}
类Tmultikey{
公众:
//实际钥匙
//可通过d_primary和d_secondary访问,
//或primary()和secondary()
MULTIKEYDEF(主,标准::字符串);
MULTIKEYDEF(辅助,无符号整数);
//强制性的
布尔运算符<(t多键常量和mk)常量{
if(primary()