C++哈希表概念及常用函数方法

实现哈希表的两种方法:

哈希(散列)函数的定义

 关键值key:

实现过程:

 键值对和Entry(一个意思)

哈希冲突:

 处理哈希冲突的方法:

1、开放寻址法

2、拉链法

3、冲突过多

哈希表的扩容:


常用的函数方法!!!:

https://blog.csdn.net/Peealy/article/details/116895964?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162942757216780357268753%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=162942757216780357268753&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v29-5-116895964.pc_search_result_cache&utm_term=C%2B%2B%E5%93%88%E5%B8%8C%E8%A1%A8%E7%9A%84%E6%9F%A5%E6%89%BE%E5%87%BD%E6%95%B0&spm=1018.2226.3001.4187

本文根据以下地址进行再一次整理

https://blog.csdn.net/sinat_33921105/article/details/103344078?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162613581416780262550821%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=162613581416780262550821&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-103344078.first_rank_v2_pc_rank_v29&utm_term=%E5%93%88%E5%B8%8C%E8%A1%A8&spm=1018.2226.3001.4187

首先我们需要知道的是哈希表的本质是一个数组

实现哈希表的两种方法:

1、数组+链表

2、数组+二叉树

哈希(散列)函数的定义

 关键值key:

就比如想要去查一个人的电话号码,那么此时我们可以将他的名字当作是关键词。

实现过程:

 键值对和Entry(一个意思)

键值对,就是我们经常说的key-value,简单点说就是一个值对应另外一个值,比如a对应b,那么a就是key,b是value,哈希表存放的就是这样的键值对,在哈希表中是通过哈希函数将一个值映射到另外一个值的,所以在哈希表中,a映射到b,a就叫做键值,而b呢?就叫做a的哈希值,也就是hash值。

总结下来就是键值对和Entry保存的是key和value两个值

哈希冲突:

比如现在张三和李四就发生了哈希冲突

 处理哈希冲突的方法:

1、开放寻址法

这里所说的开放寻址法其实简单来说就是,既然位置被占了,那就另外再找个位置不就得了,怎么找其他的位置呢?这里其实也有很多的实现,我们说个最基本的就是既然当前位置被占用了,我们就看看该位置的后一个位置是否可用,也就是1的位置被占用了,我们就看看2的位置,如果没有被占用,那就放到这里呗,当然,也有可能2的位置也被占用了,那咱就继续往下找,看看3的位置,一次类推,直到找到空位置。

2、拉链法

 拉链法则不同,还是在该位置,可是,该位置被占用了咋整,这里采用的是链表,就像图中所示,现在张三和李四都要放在1找个位置上,但是张三先来的,已经占了这个位置,待在了这个位置上了,那李四呢?解决办法就是链表,这时候这个1的位置存放的不单单是之前的那个Entry了,此时的Entry还额外的保存了一个next指针,这个指针指向数组外的另外一个位置,将李四安排在这里,然后张三那个Entry中的next指针就指向李四的这个位置,也就是保存的这个位置的内存地址,如果还有冲突,那就把又冲突的那个Entry放在一个新位置上,然后李四的Entry中的next指向它,这样就形成了一个链表。

3、冲突过多

如果冲突过多的话,这块的链表会变得比较长,怎么处理呢?这里举个例子吧,拿java集合类中的HashMap来说吧,如果这里的链表长度大于等于8的话,链表就会转换成树结构,当然如果长度小于等于6的话,就会还原链表。以此来解决链表过长导致的性能问题。

中间有个7作为一个差值,来避免频繁的进行树和链表的转换,因为转换频繁也是影响性能的啊。

哈希表的扩容:

当哈希表被占的位置比较多的时候,出现哈希冲突的概率也就变高了,所以很有必要进行扩容。

那么这个扩容是怎么扩的呢?这里一般会有一个增长因子的概念,也叫作负载因子,简单点说就是已经被占的位置与总位置的一个百分比,比如一共十个位置,现在已经占了七个位置,就触发了扩容机制,因为它的增长因子是0.7,也就是达到了总位置的百分之七十就需要扩容。

还拿HashMap来说,当它当前的容量占总容量的百分之七十五的时候就需要扩容了。

而且这个扩容也不是简单的把数组扩大,而是新创建一个数组是原来的2倍,然后把原数组的所有Entry都重新Hash一遍放到新的数组。因为数组扩大了,所以一般哈希函数也会有变化,这里的Hash也就是把之前的数据通过新的哈希函数计算出新的位置来存放。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值