C++HashTable、unordered_map 判断某个键是否存在

参考资料:
HashTable、函数对象 学习笔记

HashTable

概述:通过数组+链表的形式,结合hash算法,查找和插入的时间复杂度为常数级。

1. HashTable 结构

(1)表面认识注释的内容会在后面解析,刚开始学习,我们先看大体,再看细节。

  • 组成架构:该数据结构包含多个桶bucket[1],然后每个桶里面可以放很多数值[2]。
  • 插入逻辑:对于一个新来的数值key[3],通过一个简单的运算[4],确定该数值key应该放那个桶,然后把它丢进去[5]即可。
  • 查找逻辑:对于需要被查找的数值key,参考插入逻辑(先通过一个运算确定它在哪个桶),再去这个桶里面逐一遍历出来。
    (2)稍微深入的学习
    [1] 多个桶bucket:这是通过顺序数组来实现的。
    [2] 每个桶里面可以放很多数值:实际上,每个桶存储的都是一个指针,该指针指向一条链表。
    [3] key:放入的数值,不限定类型。在C++层面,如果是单一类型,那么可以对应标准库的unodered_set。如果是键值对(结构体),那么可以对应标准库的unodered_map。
    [4] 简单的运算:这个是hash运算。给定指定数据,hash运算会将其转换为一串数字
    [5] 把它丢进去:这个是hash冲突的处理方法,如果多个数据都hash到同一个桶,那么我们将这个视为hash冲突。而这里处理冲突的方法,就是使用一条链表,将所有hash到这个桶的数据都串起来,然后只需把链表头指针放到桶里面就行,这个处理方案的方法被称为链地址法。
    (3)结构总结
    hashtable的结构利用hash运算,将数值映射到某个桶。如果出现冲突,那么就使用链表处理冲突。由于hash运算不需要复杂的运算,所以使得他的查找效率和插入效率非常高。
    (4)其他问题
    Q:后期数据太多,链表太长影响效率?
    A:可以设定阈值,当达到阈值时,则进行重哈希rehash(),将当前数组数据迁移到更大的数组。
    (5)参考资料
    上面内容主要从以下博文学习得到,建议感兴趣的同学可以细看下面的文章。
    CSDN:hashtable源码学习

2. HashTable 对应的标准库

C++新标准中有2个STL容器是用hashtable作为底层实现的:
(1)unodered_set,能够存储单类型的容器。例如建立一个字符串类型的hashtable。
(2)unodered_map,能够存储键值对的容器。例如建立一个 <姓名,年龄>的hashtable。

3. unodered_set使用示例

关于标准库的使用,如果是int,string,float这些基本类型,那么STL自带的hash函数能够处理,那么建立时只需传递数据类型。如:unodered_set age_set;//建立1个int类型的hashtable
unodered_map<string, age> person_map;//建立1个<string, age>类型的hashtable
若是其他类型,则还需要传递hash函数以及比较函数。而这2个函数一般通过函数对象的形式的传递。下面代码使用了函数对象。若对函数对象不熟悉,参考原文连接:https://www.cnblogs.com/toulanboy/p/13766990.html

/*
unordered_set的样例代码。
*/
# include<iostream>
# include<unordered_set>
using namespace std;

//定义1个类
class Point{
public:
    int x;
    int y;
    Point(int x, int y){
        this->x = x;
        this->y = y;
    }
};
//定义Point的hash类
//由于其重载了(),故其实例化后的对象,类似于函数指针。
class PointHash{
    public:
    size_t operator()(const Point& p)const{
        //这里调用STL的hash为我们计算中间值
        return hash<int>()(p.x) + hash<int>()(p.y);
    }
};
//定义Point的equal类
//由于其重载了(),故其实例化后的对象,类似于函数指针。
class PointEqual{
    public:
    bool operator()(const Point& a, const Point& b)const{
        return a.x == b.x;
    }
};

int main(){

    unordered_set<Point, PointHash, PointEqual> my_set;
    my_set.insert(Point(11, 22));

    for(auto it = my_set.begin(); it != my_set.end(); ++it){
        cout << it->x << ","<< it->y << endl;
    }
    /*
    输出:11, 22
    */

    auto result = my_set.find(Point(11, 22));
    if(result != my_set.end()){
        cout << result->x << ","<< result->y << endl;
    }
    /*
    输出:11, 22
    author's blog == http://www.cnblogs.com/toulanboy/
    */
    return 0;
}

其余参考资料:
CSDN:hashtable源码学习
C++文档-unodered_map
unordered_map的Hash函数和等价准则
C++ STL 之 unordered_set 介绍

unordered_map 判断某个键是否存在

原文链接

unordered_map c++ reference 是c++ 哈希表的实现模板,在头文件<unordered_map>中,存储key-value的组合,unordered_map可以在常数时间内,根据key来取到value值。如何判断unordered_map 判断某个键是否存在呢?

find函数。

iterator find ( const key_type& key );
       
       

如果key存在,则find返回key对应的迭代器,如果key不存在,则find返回unordered_map::end。因此可以通过

map.find(key) == map.end()
       
       

来判断,key是否存在于当前的unordered_map中。

Count函数

size_type count ( const key_type& key ) const
       
       
count函数用以统计key值在unordered_map中出现的次数。实际上,c++ unordered_map不允许有重复的key。因此,如果key存在,则count返回1,如果不存在,则count返回0.



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值