海量数据去重的Hash、bitmap、BloomFilter、分布式一致性hash

总体知识脉络

在这里插入图片描述

背景

  • 使用 word 文档时,word 如何判断某个单词是否拼写正确?
  • 网络爬虫程序,怎么让它不去爬相同的 url 页面?
  • 垃圾邮件过滤算法如何设计?
  • 公安办案时,如何判断某嫌疑人是否在网逃名单中?
  • 缓存穿透问题如何解决?

需求

  从海量数据中查询某字符串是否存在

平衡二叉树

在这里插入图片描述

  不论是AVL还是红黑树,在“海量数据”数据面前都是不合适的,因为红黑树会将key,即数据存储起来,而海量的数据会导致内存不足。并且设计到字符串比较,效率也是很慢的。所以在这个需求下,用树相关的数据结构是不合适的。
 
扩展:

  • c++标准库(STL)中的set和map结构都是采⽤红⿊树实现的,它增删改查的时间复杂度是O(log2N)。set和map的关键区别是set不存储val字段。
  • 优点:存储效率⾼,访问速度⾼效
  • 缺点:对于数据量⼤且查询字符串⽐较⻓且查询字符串相似时将会是噩梦

散列表hashtable

  散列表构成:数组+hash函数。它是将字符串通过hash函数⽣成⼀个整数再映射到数组当中(所以散列表不需要”比较字符串“,而红黑树需要),它增删改查的时间复杂度是o(1)。
 
注意:散列表的节点中 kv 是存储在一起的

struct node {
   
	void *key;
	void *val;
	struct node *next;
};

扩展:

  • c++标准库(STL)中的unordered_map<string, bool>是采⽤hashtable实现的
  • hashtable中节点存储了key和val,hashtable并没有要求key的⼤⼩顺序,我们同样可以修改代码让插⼊存在的数据变成修改操作
  • 优点:访问速度更快;不需要进⾏字符串⽐较
  • 缺点:需要引⼊策略避免冲突,存储效率不⾼;空间换时间

hash函数

  hash函数:映射函数 Hash(key)=addr ;hash 函数可能会把两个或两个以上的不同 key 映射到同一地址,这种情况称之为冲突(或者hash 碰撞);
  hash函数的作用:避免插⼊的时候字符串的⽐较,hash函数计算出来的值通过对数组⻓度的取模能随机分布在数组当中。

选择hash

如何选取hash函数?

  • 选取计算速度快
  • 强随机分布(等概率、均匀地分布在整个地址空间)
      murmurhash1,murmurhash2,murmurhash3,siphash(redis6.0当中使⽤,rust等大多数语言选用的hash算法来实现hashmap),cityhash 都具备强随机分布性。siphash 主要解决字符串接近的强随机分布性,所以如果要hash字符串的话,优先选用siphash。

负载因子

  用来形容散列表的存储密度。数组存储元素的个数 / 数据长度;负载因子越小,冲突越小,负载因子越大,冲突越大。

冲突处理

  • 拉链法
      引用链表来处理哈希冲突,也就是将冲突元素用链表链接起来,这也是常用的处理冲突的⽅式。但是可能出现一种极端情况,冲突元素比较多,该冲突链表过长,这个时候可以将这个链表转换为红黑树。由原来链表时间复杂度 转换为红黑树时间复杂度 ,那么判断该链表过长的依据是多少?可以采⽤超过 256(经验值)个节点的时候将链表结构转换为红黑树结构。
    在这里插入图片描述

  • 开放地址法
      将所有的元素都存放在哈希表的数组中,不使用额外的数据结构;一般使用线性探查的思路解决,具体步骤如下:
      1. 当插⼊新元素的时,使⽤哈希函数在哈希表中定位元素位置
      2. 检查数组中该槽位索引是否存在元素。如果该槽位为空,则插⼊,否则3
      3. 在 2 检测的槽位索引上加⼀定步⻓接着检查2
       加⼀定步⻓分为以下几种:
        1. i+1,i+2,i+3,i+4, … ,i+n
        2. 在这里插入图片描述
        这两种都会导致同类hash聚集,也就是近似值它的hash值也近似。那么它的数组槽位也靠近,形成hash聚集。第⼀种同类聚集冲突在前,第⼆种只是将聚集冲突延后。
        3. 可以使⽤双重哈希来解决上⾯出现hash聚集现象

在.net HashTable类的hash函数Hk定义如下:
Hk(key) = [GetHash(key) + k * (1 + (((GetHash(key) >> 5) + 1) % (hashsize – 1)))] % hashsize
在此 (1 + (((GetHash(key) >> 5) + 1) % (hashsize – 1))) 与 hashsize 互为素数(两数互为素数表示两者没有共同的质因⼦)
执⾏了 hashsize 次探查后,哈希表中的每⼀个位置都有且只有⼀次被访问到,也就是说,对于给定的 key,对哈希表中的同⼀位置不会同时使⽤ Hi 和 Hj;
具体原理:https://www.cnblogs.com/organic/p/6283476.html

Stl中unordered_*散列表实现

  在 STL 中 unordered_map 、 unordered_set 、unordered_multimap 、 unordered_multiset 四兄弟底层实现都是散列表;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值