C++ 无序关联容器

C++ 11标准当中新增加了四个无序关联容器,分别是
unordered_map 映射
unordered_multimap 多重映射
unordered_set 集合
unordered_multiset 多重集合

与普通的map和set的基本功能一样,但是内部实现方式却完全不同。
map与set的实现方式为红黑树
unordered_map和unordered_set的实现方式为哈希函数,所以无序关联容器不会根据key值对存储的元素进行排序。

unordered_map

插入操作:

#include<bits/stdc++.h>
using namespace std;
typedef pair<string,size_t> pss;
int main()
{
    ios::sync_with_stdio(false);

    unordered_map<string,size_t> u_map;
    pss p1={"efg",2};

    string s="abc";
    u_map[s]++;//使用下标插入

    u_map.insert(p1);//使用nsert函数插入一个pair

    u_map.insert({{"www",2},{"wqwe",3}});//插入一个初始化列表


    vector<pss> vp={{"wrrr",2},{"ttt",3}};

    u_map.insert(vp.begin(),vp.end());//插入一个迭代器范围

    for(auto x:u_map)
        cout<<x.first<<" "<<x.second<<endl;
    return 0;
}

查找与删除操作

查找函数:find

与其他容器当中的find方法相同,参数内容可以是迭代器,也可以是key值。
返回内容为迭代器,如果查找内容不存在,则返回迭代器尾部。

unordered_map<string,size_t> u_map;
vector<pss> vp={{"wrrr",2},{"ttt",3},{"www",3},{"qq",10}};
u_map.insert(vp.begin(),vp.end());
auto it=u_map.find("qq");
if(it!=u_map.end())
    cout<<it->first<<" "<<it->second<<endl;

删除函数:earse

与其他容器当中的erase方法相同,参数中内容可以是迭代器,也可以是key值。

unordered_map<string,size_t> u_map;
vector<pss> vp={{"wrrr",2},{"ttt",3},{"www",3},{"qq",10}};
u_map.insert(vp.begin(),vp.end());

u_map.erase("www");//直接按照key值删除

for(auto x:u_map)
    cout<<x.first<<" "<<x.second<<endl;

桶管理

由于无序关联容器的实现是基于hash函数,那么就需要解决冲突问题,解决冲突的办法比较常用有开放地址法和拉链法。在C++的unordered_map当中,采用的是”桶”的方法,也就是出现冲突的元素都存放在一个桶里。用拉链法的图来做个例子

这里写图片描述

在unordered_map当中所使用的哈希策略可以通过函数重载由用户自定义。

遍历每个桶,并输出桶中的元素

    unordered_map<string,size_t> u_map;
    vector<pss> vp={{"wrrr",2},{"ttt",3},{"www",3},{"qq",10}};
    u_map.insert(vp.begin(),vp.end());


    for(auto i=0;i<u_map.bucket_count();i++)
    {
        for(auto it=u_map.begin(i);it!=u_map.end(i);it++)//迭代器中添加参数,选择桶的编号
        {
            cout<<"bucket: "<<i<<" "<<it->first<<" "<<it->second<<endl;
        }

    }

如何查看要存入的内容经过hash函数处理以后的hash值?可以使用hash_function函数。

    typedef unordered_map<string,size_t> string_int_map
    unordered_map<string,size_t> u_map;
    vector<pss> vp={{"wrrr",2},{"ttt",3},{"www",3},{"qq",10}};
    u_map.insert(vp.begin(),vp.end());

    string_int_map::hasher fn=u_map.hash_function();

    for(auto it=vp.begin();it!=vp.end();it++)
    {
        cout<<it->first<<"的哈希值是: "<<fn(it->first)<<endl;
    }

这里写图片描述

自定义类型

在unordered_map当中对结构体或者是class进行操作需要重载==运算符,同时自定义hash函数。

#include<bits/stdc++.h>
using namespace std;

struct node
{
    string name;
    int number;
    node(){}
    bool operator==(const node& n) const//重载==运算符
    {
        return name==n.name;
    }
};

struct myhash//自定义hash函数
{
    size_t operator()(const node &n) const
    {
        return n.name.size();//按照名字的长度当做hash值
    }
};
int main()
{
    ios::sync_with_stdio(false);

    unordered_map<node,size_t,myhash> u_map;

    node n;
    n.name="mike";
    n.number=100;

    u_map.insert({n,10});


    return 0;
}

如果结构体或者类当中使用系统当中按照某个成员作为来取hash值的,可以进行如下操作
例如定义了一个结构体,里面有num和res两个int型成员,现在我想把这个结构体存储到unordered_set当中,其中hash的值按照res的哈希函数来实现,又不想自己写,希望能用系统自带的对int处理的hash函数。

typedef unordered_set<int> usi;

struct node
{
    int num;
    int res;
    node(int n,int r){ num = n, res = r;}
    bool operator==(const node& n) const//重载==运算符
    {
        return res==n.res;
    }
};
struct myhash
{
    size_t operator()(const node &n) const
    {
        usi::hasher fn= usi().hash_function();
        //usi是一个unordered_set<int>
        //选取它的哈希函数作为我们定义结构体当中的哈希函数
        return fn(n.res);//处理res值后返回即可
    }
};
//声明的时候这样使用unordered_set<node,myhash> 

unordered_set的操作与性质与unordered_map大致类似。

在效率上,hash的操作时间复杂度是O(1),但是在真实的情况下,需要对hash的函数进行详细的设计,否则效率和内存方面的开销会很大。

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值