将 typedef 映射插入哈希表

发布于 2024-11-19 05:16:22 字数 2275 浏览 5 评论 0原文

在下面的程序中,我有一个 typedef 映射。我想做的是实现一个哈希表。我正在尝试使用 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;
}

我感谢任何帮助或意见。

阅读 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;

In the program below I've a typedef map. What I want to do is to implement a hash table. I'm trying to use unordered_map since I heard that is the efficient as it takes O(1) time. I use my typedef map everywhere in my main program (another program that I'm working on) so I don't want to change that. I want to implement hash table in one of the functions and I'm trying to figure out how to insert the contents of my map into the hash table and search for the key later. I've inserted a comment in two places where I'm having trouble. Please help.

#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;
}

I appreciate any help or comments.

After reading Jason's comments I understand why i cannot use a std::set as a key in unordered_map so I tried to use std::string as a key but the find function won't work. Could you please help me.

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

锦爱 2024-11-26 05:16:22

要完成这项工作,您缺少的基本元素是为您用作密钥的 std::set 定义一个哈希函数。 STL 已经为 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
        }
    };
}

上面的函子对象将返回 size_t 的整数类型,并采用 std::set > 作为参数。您必须在 namespace std 内部定义它,以便 std::unordered_map 能够识别它。一个“简单”的算法可能只是简单地对元素求和,因为您有一组 int 类型。有更复杂的算法可以减少冲突的数量,而这种简单的算法会以牺牲散列时间为代价而产生冲突。不过,一旦定义了这个,将 std::set 键值插入 unordered_map 以及创建新的键值和在哈希表中找到它们。

您可以在以下位置查看源代码的示例: http://ideone.com/DZ5jm

编辑:Jason's 代码放在这里供参考:

#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;
}

The basic element you're missing to make this work is to define a hashing function for your std::set that you're using as the key. The STL already defines equality and lexicographical ordering for a std::set, so you can use it as the key-value in a std::map as-is without any problems. It does not define a hash function though, so that is something you're going to have to-do by overloading std::hash. This is fairly straight-forward, and can be done by defining the following function:

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
        }
    };
}

The above functor object would return an integral type of size_t, and would take a std::set as the argument. You'll have to define it inside of namespace std so that std::unordered_map will recognize it. An "easy" algorithm could be simply summing the elements since you have a set of type int. There are more complex algorithms out there that would reduce the number of collisions such a simple algorithm would create at the expense of hashing time. Once you have this defined though, you shouldn't have any problems inserting your std::set key-values into an unordered_map, as well as creating new key-values and finding them in the hash table.

You can see an example of your source-code working at: http://ideone.com/DZ5jm

EDIT: Jason's code placed here for reference:

#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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文