听起来你想要一个有序映射,一个允许 O(1) 查找但记住插入顺序(用于迭代顺序)的哈希映射。幸运的是,C++ 中存在一个有效的实现:
https://github.com/Tessil/ordered-map
自述文件中的一个示例是:
#include <iostream>
#include <tsl/ordered_map.h>
int main()
{
tsl::ordered_map<char, int> map = {{'d', 1}, {'a', 2}, {'g', 3}};
map.insert({'b', 4});
map['h'] = 5;
map['e'] = 6;
map.erase('a');
// {d, 1} {g, 3} {b, 4} {h, 5} {e, 6}
for(const auto& key_value : map) {
std::cout << "{" << key_value.first << ", " << key_value.second << "}" << std::endl;
}
return 0;
}
您也可以像 Python 的有序映射一样实现它,它使用链表来跟踪插入顺序。一个优点是更有效的删除(Tessil 的有序映射有O(n) 删除,而链表/映射将是平均O(1))。假设映射通常存储Key, T 类型的键/值类型,您将在链表中存储T,并将迭代器存储为内部 unordered_map 的值类型。然后,您将包装该类和任何迭代器,以确保它像普通的哈希图一样从外部运行。
基本大纲如下所示(如果不接受 O(n) 删除,则其余部分由您实现)。使用列表是因为它们不会在删除元素时使迭代器无效,并且映射用于查找正确的列表迭代器以按键删除。满足所有大的 O 问题,尽管有一些开销。
#include <list>
#include <unordered_map>
template <
typename Key,
typename T,
typename Hash = std::hash<Key>,
typename KeyEqual = std::equal_to<Key>,
typename Allocator = allocator<std::pair<Key, T>>
>
class ordered_map
{
public:
using key_type = Key;
using mapped_type = T;
// ....
private:
using list_type = list<T, typename std::allocator_traits<Allocator>::template rebind_alloc<T>>;
using list_iterator = typename list_type::iterator;
using map_type = std::unordered_map<
Key, list_iterator, Hasah, KeyEqual,
typename std::allocator_traits<Allocator>::template rebind_alloc<std::pair<Key, list_iterator>>
>;
list_type list_;
map_type map_;
};