关于迭代器顺序的c ++ std :: map问题

时间:2010-03-22 21:13:49

标签: c++ map iterator

我是一个尝试使用地图的C ++新手,所以我可以获得find()方法的恒定时间查找。

问题在于,当我使用迭代器遍历地图中的元素时,元素的显示顺序与它们放置在地图中的顺序不同。

在不维护其他数据结构的情况下,有没有办法在按顺序迭代的同时保持恒定的时间查找能力?

请告诉我。

谢谢, JBU

编辑:感谢让我知道map :: find()不是恒定的时间。

8 个答案:

答案 0 :(得分:11)

在没有维护其他数据结构的情况下,有没有办法在按顺序迭代的同时保持恒定的时间查找能力?

不,那是不可能的。为了获得有效的查找,容器将需要以有效查找的方式对内容进行排序。对于std :: map,这将是某种类型的排序顺序;对于std :: unordered_map,这将是一个基于密钥哈希的订单。

在任何一种情况下,订单都会与添加订单的顺序不同。

答案 1 :(得分:6)

首先,std::map保证O(log n)查找时间。您可能正在考虑std::tr1::unordered_map。但是,根据定义,牺牲任何顺序来获得恒定时间查找。

你必须花一些时间,但我认为你可以用boost::multi_index_container来做你想做的事。

答案 2 :(得分:3)

如果对原始订单中的密钥使用vector而使用map来快速访问数据呢?

这样的事情:

vector<string> keys;
map<string, Data*> values;

// obtaining values
...
keys.push_back("key-01");
values["key-01"] = new Data(...);
keys.push_back("key-02");
values["key-02"] = new Data(...);
...

// iterating over values in original order
vector<string>::const_iterator it;
for (it = keys.begin(); it != keys.end(); it++) {
    Data* value = values[*it];
}

答案 3 :(得分:2)

应用于密钥时,项目按operator<(默认)排序。

PS。 std :: map不保证不断查看。
它保证了O(ln(n))

的最大复杂度

答案 4 :(得分:2)

我实际上......后退。

如果您想保留插入元素的顺序,或者通常要控制顺序,您需要一个您将控制的序列:

  • std::vector(是的还有其他人,但默认情况下使用此一个)

您可以使用std::find算法(来自<algorithm>)在向量中搜索特定值:std::find(vec.begin(), vec.end(), value);

哦,是的,它具有线性复杂度O(N),但对于小型集合,它应该无关紧要。

否则,您可以按照已经建议的那样开始查看Boost.MultiIndex,但对于初学者,您可能会有点挣扎。

所以,暂时推卸复杂性问题,并想出一些有效的方法。当你更熟悉这门语言时,你会担心速度。

答案 5 :(得分:1)

首先,std::map不是恒定时间查找。它是O(log n)。我以为我应该直截了当。

无论如何,如果要使用不同的排序,则必须指定自己的比较功能。没有可以按插入时间排序的内置比较函数,但是,如果您的对象包含时间戳字段,您可以安排在插入时设置时间戳,并使用按时间戳比较。

答案 6 :(得分:1)

Map不是用于按某种顺序放置元素 - 使用向量。

如果您想在地图中找到某些内容,则应使用[操作员

按键搜索

如果您同时需要:迭代和按键搜索,请参阅此topic

答案 7 :(得分:0)

是的,您可以创建这样的数据结构,但不使用标准库...原因是标准容器可以嵌套但不能混合。

实现例如地图数据结构没有问题,其中所有节点也按插入顺序处于双向链表中,或者例如所有节点都在数组中的地图。在我看来,这些结构中的一个可能是您正在寻找的(取决于您喜欢哪种操作速度快),但是使用标准容器构建它们都是微不足道的,因为每个标准容器(vectorlistset,...)希望成为访问所包含元素的唯一途径。

例如,我发现在许多情况下,在多个双向链表中同时拥有节点是有用的,但是你不能使用std::list来做到这一点。