【问题标题】:a C++ hash map that preserves the order of insertion [duplicate]保留插入顺序的 C++ 哈希映射 [重复]
【发布时间】:2010-12-26 08:29:44
【问题描述】:

我有以下代码:

#include <iostream>
#include "boost/unordered_map.hpp"

using namespace std;
using namespace boost;

int main()
{

    typedef unordered_map<int, int> Map;
    typedef Map::const_iterator It;

    Map m;
    m[11] = 0;
    m[0]  = 1;
    m[21] = 2;

    for (It it (m.begin()); it!=m.end(); ++it)
        cout << it->first << " " << it->second << endl;

    return 0;
}

但是,我正在寻找保留顺序的东西,以便稍后我可以按照插入元素的相同顺序迭代元素。在我的电脑上,上面的代码不保留订单,并打印以下内容:

 0 1
11 0
21 2

我想也许我可以使用boost::multi_index_container

typedef multi_index_container<
    int,
    indexed_by<
        hashed_unique<identity<int> >,
        sequenced<>
    >
> Map;

谁能告诉我如何使用这个容器(或任何其他合适的容器)实现我的原始代码,以便迭代器遵循插入顺序?

【问题讨论】:

  • 维护一个单独的列表来跟踪插入顺序是不可能的吗?
  • 很遗憾这个问题被关闭了,因为std::map 需要 O(n lg n) 的构建时间,所以它不能在 O(n) 时替代 std::unordered_map

标签: c++ unordered-map html-lists multi-index


【解决方案1】:
#include <iostream>
#include "boost/unordered_map.hpp"

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>

using namespace std;
using namespace boost;
using namespace boost::multi_index;


struct key_seq{};
struct key{};

struct Data_t
{
    int key_;
    int data_;
    Data_t (int key_v, int data_v) : key_(key_v), data_(data_v) {}
};

int main()
{
    typedef multi_index_container<
        Data_t,
        indexed_by<
            hashed_unique<tag<key>,  BOOST_MULTI_INDEX_MEMBER(Data_t,int,key_)>,
            sequenced<tag<key_seq> >
        >
    > Map;

    typedef Map::const_iterator It;

    typedef index<Map,key>::type Map_hashed_by_key_index_t;
    typedef index<Map,key>::type::const_iterator  Map_hashed_by_key_iterator_t;

    typedef index<Map,key_seq>::type Map_sequenced_by_key_index_t;
    typedef index<Map,key_seq>::type::const_iterator  Map_sequenced_by_key_iterator_t;

    Map m;
    m.insert(Data_t(11,0));
    m.insert(Data_t(0,1));
    m.insert(Data_t(21,1));

    {
        cout << "Hashed values\n";
        Map_hashed_by_key_iterator_t i = get<key>(m).begin();
        Map_hashed_by_key_iterator_t end = get<key>(m).end();
        for (;i != end; ++i) {
            cout << (*i).key_ << " " << (*i).data_ << endl;
        }
    }

    {
        cout << "Sequenced values\n";
        Map_sequenced_by_key_iterator_t i = get<key_seq>(m).begin();
        Map_sequenced_by_key_iterator_t end = get<key_seq>(m).end();
        for (;i != end; ++i) {
            cout << (*i).key_ << " " << (*i).data_ << endl;
        }
    }

    return 0;
}

【讨论】:

  • 谢谢。我在 boost 1.41 上收到上述代码的编译错误。
  • 我已经用 Boost.1.41 和 Visual Studio 2005 测试了这个例子,一切正常。您使用什么编译器和操作系统?
  • 我在 Snow Leopard 上使用 i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1(Apple Inc. build 5646)(点 1)。我现在正在下载 gcc-4.4,希望它能与最新版本的 gcc 一起编译。
  • 抱歉,我只是打错了insert_() 而不是insert()。这是一个导致 gcc 出现问题的错误。我修复了代码。
  • 与gcc版本或Boost版本无关
【解决方案2】:

您可以尝试使用地图和矢量的组合创建有序地图。

  • 向量可以持有这对密钥和 价值。
  • 向量迭代器可以用作 遍历有序映射的迭代器。
  • map 可以用来访问元素 更快。

【讨论】:

  • 我在 C++ 方面不是很有经验。你能给我一个你的建议的示例实现吗?
猜你喜欢
  • 2018-08-19
  • 2017-03-17
  • 2014-04-18
  • 1970-01-01
  • 1970-01-01
  • 2017-08-28
  • 2014-02-01
  • 2017-01-05
  • 2011-10-01
相关资源
最近更新 更多