unordered_map,哈希结构

C++11中新增4个unordered系列关联式容器
unordered_map说明

  • unordered_map存储<key, value>键值对的关联式容器,其允许通过keys快速的索引到与其对应的value.
  • 在unordered_map中,键值通常作为唯一标识元素,而映射值只是一个对象,其内容与此键关联,键和映射值的类型可能不同
  • unoedered_map并没有对<key, value>按照特定的顺序排序,为了能在常数范围内找到key所在的value, unordered_map将相同哈希值得键值放在相同的桶里
  • unordered_map容器通过key访问单个元素比mao快, 但他通常在遍历子集的返回迭代方面效率较低
  • unoodered_map实现直接访问操作符operator[]
    ,允许使用key作为参数直接访问value.

unordered_map的容量

函数声明功能介绍
bool empty() const检测unordered_map是否为空
size_t size()获取unordered_map的有效元素个数

unordered_map的迭代器

函数声明功能
begin返回unordered_map第一个元素的迭代器
end返回unordered_map最后一个元素下一个位置的迭代器
cbegin返回unordered_map第一个元素的const迭代器
cend返回unordered_map最后一个元素下一个位置的const迭代器

unordered_map的元素访问

函数声明功能
operatot[]返回与key对应的value,没有一个默认值

unordered_map的查询

函数声明功能介绍
iterator find(const K& key)返回key在哈希桶中的位置
size_t count(const K& key)返回哈希桶中关键码为key的键值对的个数

unordered_map的修改操作

函数声明介绍
insert向容器中插入键值对
erase删除容器中的键值对
void clear()清空容器中有效元素个数
void swap(unordered_map&)交换两个容器中的元素
size_t bucket(const K& key)返回元素key所在的桶号

底层结构
unordered_map系列的关联式容器之所以效率比较高,在于底层实现了哈希结构
哈希结构
定义hashfunc使元素的存储位置与它的关键码之间建立一对一映射的关系
插入元素时,根据待插入元素的关键码,以hashfunc计算出该元素的存储位置,在结构中按此位置进行存放
搜索元素时,对关键码进行同样的计算,把求得的函数值当做元素的存储位置,在结构中按此位置去元素比较,若关键码相等,则搜索成功
hash(key) = key % capacity
哈希冲突
不同关键字通过哈希函数计算出相同的哈希地址,此时称为哈希冲突,这两关键字称为同义字
哈希函数
hashfunc设计原则

  • 哈希函数的定义域必须包括需要存储的全部关键码,而如果散列表允许m个地址时,其值域必须在0-(m-1)之间

  • 哈希函数计算出来的地址能均匀分布在整个空间中

  • 哈希函数应该比较简单
    常见哈希函数
    1.直接定制法
    取关键字的某个线性函数为散列地址: hash (key) = A*Key +B,
    优点: 简单,均匀,缺点: 需要提前知道关键字的分布情况
    使用场景:适合查找小且连续的场景
    2.除留余数法
    设散列表中允许的地址数为m,取一个不大于m,但最接近或者等于m的质数p(尽量选择一个素数)作为除数,按照哈希函数:Hash(key) = key% p(p<=m),将关键码转换成哈希地址
    哈希冲突解决
    两种常见的方法: 闭散列和开散列
    闭散列
    即: 开放定址法,当哈希表未满,在插入同义字时,可以把key值存放在下一个空位置(线性探测)
    线性探测: 从发生冲突的位置开始,依次向后探测,直到寻找下一个空位置为止.

  • 插入
    通过哈希函数获取插入元素在哈希表中的位置.
    如果该位置没有元素则插入新元素,如果该位置有元素发生哈希冲突,使用线性探测找到下一个空位置,插入新元素.

  • 删除
    采用闭散列删除处理哈希冲突时,不能随便物理删除哈希表中已有的元素,若直接删除元素会影响其它元素的的搜索.此时线性探测采用标记的伪删除来删除一个元素

// 哈希表每个空间给个标记
// EMPTY此位置空, EXIST此位置已经有元素, DELETE元素已经删除
enum State{EMPTY, EXIST, DELETE};

线性探测优点 : 实现简单
线性探测缺点 : 一旦发生哈希冲突 , 所有的冲突连接在一起,容易产生数据"堆积", 即: 不同关键占据了可利用空间,是寻找某关键码的位置需要多次比较,导致速率降低,因而进行二次探测
开散列
开散列法又叫链地址法(开链法),首先对关键码集合用散列函数计算散列地址,具有相同地址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中。
开单列增容
桶的个数是一定的,随着元素的不断插入,每个桶中元素的个数不断增多,极端情况下,可能会导致一个桶中链表节点非常多,会影响的哈希表的性能开散列最好的情况是:每个哈希桶中刚好挂一个节点,再继续插入元素时,每一次都会发
生哈希冲突,因此,在元素个数刚好等于桶的个数时,可以给哈希表增.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值