在我的下一个程序中,我目前正在使用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
吗?
答案 0 :(得分:9)
只需使用常规std::map
即可。请注意,这意味着您需要订购而非散列。
顺便说一下,unordered_map
是hash_map
。 “无序”只是捕获概念差异而不是实现差异,因此它是一个更好的名称。
答案 1 :(得分:1)
如果您需要足够频繁的排序顺序,那么我建议切换到map
这是一个有序的容器。插入和查找现在在复杂性上是对数的,但容器默认排序。
答案 2 :(得分:0)
为了在插入时保持元素排序,你需要使用(有序)映射,它的设计具有渐近log(N)最坏情况的插入复杂度,这是任何基于比较的排序算法的最佳结果。
要提供对现有元素的快速(平均)访问权限,您可能想要使用无序(哈希)映射。
如果两种情况都很重要,您可以手动使用两个地图,或者同时创建一些封装容器类封装地图和有序地图。
但是,此解决方案仅在读取操作(显着!)比写入操作更频繁时才有用,并且在内存消耗方面存在一些缺点(由于缓存和页面交换问题可能导致性能下降)。因此,无论如何都需要对此解决方案进行一些实验和分析。
另外,如果你的订单有一些细节,例如,你的元素是从一小组(比如1,2,... 10)的某些“rate”值排序的,那么特定的排序算法可能比map更好(因为这种排序可能不需要基于比较)
[edit] (我的最后一个例子是小范围值排序,严格来说,与std :: map的使用是不相容的,因为对于大量的元素,它显然不会产生严格的弱顺序。我不删除它,因为它在某些应用程序中有时可能是有用的情况)