提问人:mrchance 提问时间:10/26/2020 最后编辑:Ted Lyngmomrchance 更新时间:10/28/2020 访问量:1740
具有快速查找功能的 C++ 列表
C++ list with fast find
问:
我正在使用 .std::list
元素按“插入顺序”显示到列表中,而不是根据元素的值显示。
当 -ing 元素时,必须搜索整个列表。std::find()
为了加快从 O(n) 到 O(log(n)) 的“查找”速度,我可以自己实现一个哈希映射来存储元素位置,或者我可以使用提升多索引,https://www.boost.org/doc/libs/release/libs/multi_index/doc/tutorial/basics.html#list_fast_lookup。std::list
问:今天,在 C++ 17 中,是否有一种标准/通用或最佳实践方法来实现具有列表的所有属性以及快速(例如)的容器?或者,这样的容器类型是否已经存在?也许是C++20?find
remove
编辑/注意:列表中元素的顺序是相关的,因此不能直接使用 std::map。
答:
由于 a 的迭代器在插入和删除之间仍然有效(当然,您删除的元素除外),因此您可以维护 secondaray 数据结构类型(如果更合适,则为 a)。std::list
std::map <my_key, my_list_iterator>
std::unordered_map
然后,每当您添加或删除列表条目时,对您的列表条目执行相同的操作,您就完成了。当然,您可以使用 O(log(n)) (或 O(1)) 复杂度进行搜索。std::map / unordered_map
评论
目前答案的部分和非常原始的(原型)实现 https://stackoverflow.com/a/64539693/11608725(由 Paul Sanders 撰写):
#include <unordered_map>
#include <list>
#include <iterator>
#include <iostream>
using std::unordered_map;
using std::list;
using std::make_pair;
using std::begin;
using std::end;
using std::prev;
using std::cout;
template <typename T>
struct fastlist {
list<T> l;
unordered_map<T, typename list<T>::iterator> m;
void push_front(T e) {
l.push_front(e);
m.insert(make_pair(e, begin(l)));
}
void push_back(T e) {
l.push_back(e);
m.insert(make_pair(e, prev(end(l))));
}
auto find(T e) {
return m[e];
}
void remove(T e) {
auto it = m[e];
m.erase(*it);
l.erase(it);
}
};
int main() { // Giving it a spin
fastlist<int> f;
f.push_back(3);
f.push_back(4);
f.push_back(5);
f.push_front(2);
f.push_front(1);
f.remove(3);
f.remove(5);
f.remove(1);
f.push_back(200);
f.push_front(-100);
cout << *f.find(4);
}
演示:https://godbolt.org/z/jdnvdM
除其他外,此原型缺少用于实现自定义容器的迭代器方法,有关此内容的信息,请参阅:如何实现 STL 样式的迭代器并避免常见的陷阱?
(编辑:Ted Lyngmo在下面的评论中提供了更好的版本:https://godbolt.org/z/6xfbq7)。
如果这种容器开箱即用,那真的会很整洁。以及其他基于更基础的容器建模/派生的容器,但增加了反映特定使用情况的特定性能优势。如果有人知道任何提供这种专用容器的图书馆,请告诉;-)
评论
find()
list<T>::iterator
list
find
非常简短且易于理解的指南(基于单个示例),介绍如何使用 Boost MultiIndex 实现具有所需功能的容器 https://stackoverflow.com/a/39510606/11608725
对我来说,它比涵盖所有可能用途的更正式的风格 https://www.boost.org/doc/libs/release/libs/multi_index/doc/tutorial/basics.html#list_fast_lookup 更容易理解(尽管它也使用示例)。
评论
std::map
std::vector
std::list
std::list