【问题标题】:ordered version of unordered_map?unordered_map 的有序版本?
【发布时间】:2011-10-20 11:45:16
【问题描述】:

在我的以下程序中,我目前使用unordered_map 只是因为我想要 O(1) 搜索/插入时间。但现在我想订购这些物品。每次对它进行排序是非常低效的。我的选择是什么?我读到hash_map 完成了这项工作,但我读到的文章非常令人困惑,或者对我来说理解起来相当复杂。插入/搜索hash_map 的复杂性是什么?它真的是有序的吗?如果是这样,它是否在 C++0x 中定义,我该如何实现它?如果不是我还能用什么?谢谢。

include <iostream>
#include <iterator>
#include <set>
#include <vector>
#include <unordered_map>

using namespace std;


template <class T>
inline void hash_combine(std::size_t & seed, const T & v)
{
  std::hash<T> hasher;
  seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}

template <typename C> struct ContainerHasher
{
  typedef typename C::value_type value_type;
  inline size_t operator()(const C & c) const
  {
    size_t seed = 0;
    for (typename C::const_iterator it = c.begin(), end = c.end(); it != end; ++it)
    {
      hash_combine<value_type>(seed, *it);
    }
    return seed;
  }
};


typedef std::set<int> my_set;
typedef std::vector<int> my_vector;
typedef std::unordered_map<my_set, my_vector, ContainerHasher<std::set<int>>> my_map;
typedef my_map::iterator m_it;

void print(my_map& data)
{
        for( m_it it(data.begin()) ; it!=data.end(); ++it)
        {
                cout << "Key : ";
                copy(it->first.begin(), it->first.end(), ostream_iterator<int>(cout, " "));
                cout << " => Value: ";
                copy (it->second.begin(),it->second.end(),ostream_iterator<int>(cout," "));
                cout << endl;
        }
        cout << "---------------------------------------------------------------\n";
}

int main()
{
   my_vector v1,v2,v3;
  for(int i = 1; i<=10; ++i)
   {
      v1.push_back(i);
      v2.push_back(i+10);
      v3.push_back(i+20);
   }

   my_set s1(v3.begin(),v3.begin()+3);
   my_set s2(v1.begin(),v1.begin()+3);
   my_set s3(v2.begin(),v2.begin()+3);

   my_map m1;

   m1.insert(make_pair(s1,v1));
   m1.insert(make_pair(s2,v2));
   m1.insert(make_pair(s3,v3));

   print(m1);
   my_set s4(v3.begin(),v3.begin()+3);

   m_it it = m1.find(s4);

   if(it != m1.end())
   {
      cout << endl << "found" << endl;
   }
   else
   {
      cout << endl << "Not found" << endl;
   }
}

编辑:

我之前使用过std::map,但我有大量项目(以百万计)。所以即使物品数量如此之多,如果我想要订购,你们都推荐map吗?

【问题讨论】:

  • 你不能一边吃蛋糕一边吃。如果你放弃订单,你可以得到速度 O(1) 插入/查找 unordered_map;如果你想订购,你可以得到 insert 或 find ,或两者都变慢。

标签: c++ map c++11 hashmap unordered-map


【解决方案1】:

只需使用普通的std::map。请注意,这意味着您需要排序而不是散列。

一个unordered_map 是一个hash_map,顺便说一句。 “无序”只是捕捉概念上的差异而不是实现上的差异,因此它是一个更好的名称。

【讨论】:

  • 我在问题中添加了一些内容。请看一看。谢谢
  • @Sunil:您通常不会根据计划在其中存储的元素数量来选择 map 或 unordered_map。您通常根据需要执行的操作来选择容器。如果大多数操作都是随机访问,那么 unordered_map 可能会更好。如果大多数操作都需要顺序访问,那么 map 可能会更好。请注意,map 默认使用 std::less 来按顺序存储其元素。如果您需要不同的顺序,可以使用第三个模板参数(例如 std::map)覆盖它。
  • @Sean : map 和 unordered_map 都不提供随机访问。
  • @ildjarn:我指的是 map 或 unordered_map 的使用方式,而不是它们提供的迭代器类型。
  • @Sean :我明白;我只是想指出您的术语令人困惑。
【解决方案2】:

如果您需要足够频繁的排序顺序,那么我建议切换到map,这是一个有序容器。插入和查找现在的复杂度是对数,但容器默认排序。

【讨论】:

    【解决方案3】:

    要在插入时保持元素有序,您需要使用 (ordered) map,它的设计具有渐近 log(N) 最坏情况插入复杂度,是任何基于比较的排序算法的最佳结果。

    为了提供对现有元素的快速(平均)访问,您可能可能想要使用无序(散列)映射。

    如果这两种情况都很重要,您可以手动使用 both 地图,或者同时创建一些包装容器类来封装地图和有序地图。

    但是,此解决方案仅在读取操作(显着!)比写入操作更频繁并且具有内存消耗(由于缓存和页面交换问题可能导致性能下降)方面存在一些缺点时才有用。所以无论如何,这个解决方案都需要一些实验和分析。

    另外,如果您的排序有一些具体细节,例如,您的元素是按一小部分(例如 1,2,...10)中的一些“比率”值排序的,那么具体的排序算法可能比 map 更好(因为此排序可能不需要基于比较)

    [edit](严格来说,我最后一个按小范围值排序的示例与可能使用 std::map 不兼容,因为对于大量元素,它显然不会产生严格的弱顺序。我不会删除它,因为它有时在某些应用程序中可能很有用)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-11
      • 1970-01-01
      • 1970-01-01
      • 2011-05-16
      • 2015-09-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多