这是我的代码
map<string,int> persons;
persons["B"] = 123;
persons["A"] = 321;
for(map<string,int>::iterator i = persons.begin();
i!=persons.end();
++i)
{
cout<< (*i).first << ":"<<(*i).second<<endl;
}
预期输出:
B:123
A:321
但是它给出的输出是:
A:321
B:123
我希望它保持在map<string,int>
中插入键和值的顺序。
有可能吗?还是应该使用其他STL数据结构?哪一个?
没有标准容器可以直接执行您想要的操作。如果要保持插入顺序,显然可以使用的容器是矢量。如果您还需要按字符串查找,请使用矢量和地图。该映射通常是从字符串到向量的索引,但是由于您的数据已经是整数,因此您可能只想复制它,具体取决于您的用例。
我也认为Map并非可行之路。 Map中的键构成一个Set;单个密钥只能出现一次。在插入映射期间,映射必须搜索键,以确保它不存在或更新该键的值。为此,重要的是(在性能方面)键以及条目具有某种排序。因此,具有插入顺序的Map在插入和检索条目时效率非常低。
是,地图容器不适合您。按照您的要求,您需要以下代码:
我将投票给typedef std::vector< std::pair< std::string, int > > UnsortedMap;
Map是有序集合(模板中的第二个参数是订单函子),已设置。如果要按顺序弹出该序列中的元素,则应使用双端队列或列表或向量。
为了执行任务并高效地进行操作,地图使用哈希表和排序。因此,如果您愿意放弃插入顺序的存储以获取按键查找的便利和性能,则可以使用地图。
在插入Map时,将Map与迭代器向量一起使用。 (保证地图迭代器不会失效)
``结构比较:public binary_function {bool operator()(int a,int b){返回true;}};
代替地图,您可以将pair函数与向量一起使用!例如:
有std::unordered_map您可以签出。从第一个角度看,它似乎可以解决您的问题。
如果您不想使用Boost :: multi_index,我将概念证明类模板放在此处进行审查:
[就像Matthieu在另一个答案中所说,Boost.MultiIndex library似乎是您想要的正确选择。但是,此库在一开始使用起来可能会有些困难,特别是如果您没有太多C ++经验的话。这是您使用库来解决问题代码中确切问题的方法:
struct person {
std::string name;
int id;
person(std::string const & name, int id)
: name(name), id(id) {
}
};
int main() {
using namespace::boost::multi_index;
using namespace std;
// define a multi_index_container with a list-like index and an ordered index
typedef multi_index_container<
person, // The type of the elements stored
indexed_by< // The indices that our container will support
sequenced<>, // list-like index
ordered_unique<member<person, string,
&person::name> > // map-like index (sorted by name)
>
> person_container;
// Create our container and add some people
person_container persons;
persons.push_back(person("B", 123));
persons.push_back(person("C", 224));
persons.push_back(person("A", 321));
// Typedefs for the sequence index and the ordered index
enum { Seq, Ord };
typedef person_container::nth_index<Seq>::type persons_seq_index;
typedef person_container::nth_index<Ord>::type persons_ord_index;
// Let's test the sequence index
persons_seq_index & seq_index = persons.get<Seq>();
for(persons_seq_index::iterator it = seq_index.begin(),
e = seq_index.end(); it != e; ++it)
cout << it->name << ":"<< it->id << endl;
cout << "\n";
// And now the ordered index
persons_ord_index & ord_index = persons.get<Ord>();
for(persons_ord_index::iterator it = ord_index.begin(),
e = ord_index.end(); it != e; ++it)
cout << it->name << ":"<< it->id << endl;
cout << "\n";
// Thanks to the ordered index we have fast lookup by name:
std::cout << "The id of B is: " << ord_index.find("B")->id << "\n";
}
将产生以下输出:
B:123
C:224
A:321
A:321
B:123
C:224
The id of B is: 123
地图绝对不适合您:
“在内部,按照在构造上设置的特定严格的弱排序标准,将图中的元素从低到高的键值进行排序。”
从here中摘录。
不幸的是,STL中没有无序的关联容器,因此您可以使用vector
之类的非关联容器,也可以编写自己的:-(
除了Neil建议使用向量+映射组合之外,如果您既需要保持插入顺序又需要按键搜索的能力,还可以考虑使用boost多索引库,该库提供了以多种方式寻址的容器。] >
映射和集合旨在对数据施加严格的弱排序。斯特里克弱排序可确保没有条目为equavalent(不同于相等)。
我偶尔会遇到相同的问题,这是我的解决方案:https://github.com/nlohmann/fifo_map。它是仅标头的C ++ 11解决方案,可以用作std::map
的直接替代。
嗯,没有STL容器可以真正满足您的要求,但是有可能。
使用向量。它使您可以完全控制订购。
为了保留所有时间复杂性约束,您需要map + list: