0x0*_*0x0 3 c++ unordered-map hashtable map set
在下面的程序中,我有一个typedef map.我想要做的是实现一个哈希表.我正在尝试使用,unordered_map因为我听说这是有效的,因为它需要O(1)时间.我typedef map在我的主程序(我正在处理的另一个程序)中使用我的所有地方,所以我不想改变它.我想在其中一个函数中实现哈希表,我试图弄清楚如何将我的地图内容插入哈希表并稍后搜索密钥.我在两个我遇到麻烦的地方插了一条评论.请帮忙.
#include <iostream>
#include <vector>
#include <iterator>
#include <set>
#include <map>
#include <unordered_map>
using namespace std;
typedef vector<int> v_t;
typedef set<int> s_t;
typedef map<s_t, v_t> m_t;
typedef m_t::iterator m_it;
typedef std::unordered_map<s_t, v_t> Mymap;
int main(){
m_t sample;
for (int i = 0; i < 100; i = i+2) {
v_t v;
for(int k = 100 ; k<=105 ; ++k)
v.push_back(k);
s_t k;
k.insert(i);
sample.insert(sample.end(), make_pair(k, v));
}
//---------Debug--------------------
for( m_it it(sample.begin()) ; it!=sample.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<double>(cout," "));
cout << endl;
}
//---------------------------------
Mymap c1;
for( m_it it(sample.begin()) ; it!=sample.end(); ++it) {
c1.insert(Mymap::value_type(it->first,it->second)); // how to do this ?
}
s_t s;
s.insert(72);
if(c1.find(s)!=c1.end()) // does this work ?
cout << "Success" << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我感谢任何帮助或评论.
在阅读Jason的评论后,我理解为什么我不能使用一个std::set键作为键,unordered_map所以我试图std::string用作键,但该find功能将无法正常工作.请你帮助我好吗.
Mymap c1;
for( m_it it(sample.begin()) ; it!=sample.end(); ++it) {
v_t v1;
std::string key;
key.insert(key.begin(),it->first.begin(),it->first.end());
copy(it->second.begin(), it->second.end(),std::back_inserter(v1));
c1.insert(Mymap::value_type(std::make_pair(key,v1)));
}
string s = "72";
if((c1.find(s) != c1.end()) == true)
cout << "Success" << endl;
return 0;
Run Code Online (Sandbox Code Playgroud)
您完成此工作所缺少的基本元素是为您std::set正在使用的键作为键定义散列函数.STL已经为a定义了相等和词典排序std::set,因此您可以将其用作原样中的键值std::map而不会出现任何问题.它没有定义散列函数,所以这是你要通过重载std :: hash来做的事情.这非常简单,可以通过定义以下函数来完成:
namespace std
{
template<>
struct hash<std::set<int> > : public std::unary_function<std::set<int>, size_t>
{
size_t operator()(const std::set<int>& my_set) const
{
//insert hash algorithm that returns integral type
}
};
}
Run Code Online (Sandbox Code Playgroud)
上面的仿函数对象将返回一个整数类型size_t,并将a std::set作为参数.你必须定义它的内部namespace std,这样std::unordered_map会承认它.由于您有一组类型,因此"简单"算法可以简单地对元素求和int.有更复杂的算法可以减少冲突的数量,这样一个简单的算法会以牺牲哈希时间为代价.一旦你定义了这个,你就不应该在将std::set键值插入到键盘中时出现任何问题,也不应该unordered_map创建新的键值并在哈希表中找到它们.
您可以在http://ideone.com/DZ5jm上看到您的源代码示例
编辑:杰森的代码放在这里供参考:
#include <iostream>
#include <vector>
#include <iterator>
#include <set>
#include <map>
#include <unordered_map>
using namespace std;
namespace std
{
template<>
struct hash<set<int> > : public unary_function<set<int>, size_t>
{
size_t operator()(const std::set<int>& my_set) const
{
set<int>::iterator iter = my_set.begin();
int total = 0;
for (; iter != my_set.end(); iter++)
{
total += *iter;
}
return total;
}
};
}
typedef vector<int> v_t;
typedef set<int> s_t;
typedef map<s_t, v_t> m_t;
typedef m_t::iterator m_it;
typedef std::unordered_map<s_t, v_t> Mymap;
int main(){
m_t sample;
for (int i = 0; i < 100; i = i+2) {
v_t v;
for(int k = 100 ; k<=105 ; ++k)
v.push_back(k);
s_t k;
k.insert(i);
sample.insert(sample.end(), make_pair(k, v));
}
//---------Debug--------------------
for( m_it it(sample.begin()) ; it!=sample.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<double>(cout," "));
cout << endl;
}
//---------------------------------
Mymap c1;
for( m_it it(sample.begin()) ; it!=sample.end(); ++it) {
c1.insert(Mymap::value_type(it->first,it->second)); // how to do this ?
}
s_t s;
s.insert(72);
if(c1.find(s)!=c1.end()) // does this work ?
cout << "Success" << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)