我是一个尝试使用地图的C ++新手,所以我可以获得find()方法的恒定时间查找。
问题在于,当我使用迭代器遍历地图中的元素时,元素的显示顺序与它们放置在地图中的顺序不同。
在不维护其他数据结构的情况下,有没有办法在按顺序迭代的同时保持恒定的时间查找能力?
请告诉我。
谢谢, JBU
编辑:感谢让我知道map :: find()不是恒定的时间。
答案 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)
答案 7 :(得分:0)
是的,您可以创建这样的数据结构,但不使用标准库...原因是标准容器可以嵌套但不能混合。
实现例如地图数据结构没有问题,其中所有节点也按插入顺序处于双向链表中,或者例如所有节点都在数组中的地图。在我看来,这些结构中的一个可能是您正在寻找的(取决于您喜欢哪种操作速度快),但是使用标准容器构建它们都是微不足道的,因为每个标准容器(vector
, list
,set
,...)希望成为访问所包含元素的唯一途径。
例如,我发现在许多情况下,在多个双向链表中同时拥有节点是有用的,但是你不能使用std::list
来做到这一点。