4.哈希函数和哈希表

10.基础提升 哈希函数与哈希表等_哔哩哔哩_bilibili 的学习笔记

哈希函数f的特征:

相同的输入一定导致相同的输出

不同的输入 导致不同的输出(有可能有碰撞)

输出是均匀分布的

in—(f函数)-out —(%m取模)—新的输出在0~m-1上均匀分布

哈希表:

  基于哈希函数实现的,哈希表是均匀变长的

查找的时候通过哈希函数知道是去哪个桶(k个桶)里找 复杂度:O(k)~O(1)

每个桶链长度不超过2,扩容要logN,不超过k,扩容要logkN,

扩容:每个数据计算哈希值,全要去挂桶,加了N个字符串代价是O(N*logkN) k大点就看作每个O(1)

虚拟机:可用离线扩容机制(除去C++)

另外:开放地址法

设计RandomPool 结构

[题目]

设计一种结构,在该结构中有如下三个功能:

insert (key) :将某个key加入到该结构,做到不重复加入

delete (key) :将原本在结构中的某个key移除

getRandom() :等概率随机返回结构中的任何一个key。

[要求]

Insert、 delete和getRandom方法的时间复杂度都是0(1)

结构里需要这三个

map1(str->index)

map2(index->str)

intsize

ABC…Z 0~25

getRandom:

没有删除行为时:随机生成数0~intsize-1

有删除行为时:最好保证index上没有空洞,让最后一条记录(intsize上有)去填要删的地方,--intsize;

布隆过滤器

不会出现 黑名单误报白名单

只会可能 白名单误报黑名单

好处:极大的省空间

坏处:失误率很低 万分之一但不可避免

怎么实现?:

位图

bit  arr/bit map

基础类型数组eg:int(4字节)—->建立bit类型数组

int[] arr = new int[10]; 32bit*10->320bit

int i = 178;//获得178个bit的状态

int numIndex = 178/32;//定位哪个数

int bitIndex = 178%32;//具体这个数的哪一位的信息

int  s = ( (arr[numIndex]) >> (bitIndex))    &1

//这个数右移bitindex位,第178位的信息在这个数的最右侧,再与1&操作,就得到178位的状态

arr[numIndex] = arr[numIndex] | (1 << bitIndex)

//把第178位的状态改为1,,,将原始的信息 或操作 1左移bitindex位 后的状态

arr[numIndex] = arr[numIndex] & (~ (1 << bitIndex))

//将第178位的状态改为0

布隆过滤器的实现:

(Url:web地址)

大位图 长度为m bit数组占用m/8字节的内存

对于黑名单的第一个url1 :

U1分为几个特征块

——(fun1)——out1——(%m)——得到它是哪个格,描黑

——(fun2)——out2——(%m)——得到它是哪个格,描黑

……

k个哈希函数,得到k个位置,可能会出现某两个位置一样

然后对Url2同样的操作……到Url100亿

就建立好了

urlx 调用k个哈希函数得到哈希值取模,看看相对应的位置是否全都描黑,若有一位没有的话,说明这个urlx不在黑名单里

其中:k和m是不确定的

位图开的很大很大,m越大,越不容易失误。再根据样本数和url的特征数 去设置一个合适的k。。。(k越大,m个格中描黑的越多)

失误率随m的增大逐渐降低,失误率随k的增大先降低后急剧升高。

 计算公式:(条件:样本量n,失误率P)

m = -(n*ln P)/((ln 2)^2)

k =  ln2*m/n~~0.7*m/n;

实际失误率:

一致性哈希问题

哈希key,选择类别较多的,使得高频中频低频的都有一定的数量  (负载均衡算法,将数据均匀的分配到各个机器上,防止有的机器忙到崩溃,而有的机器闲)

一致性哈希:没有模运算

假设使用哈希函数MD5算法,返回值0~2^64-1

将整个哈希域想象成一个环

假设有三台机器m1,m2,m3,是用来存数据的,三台机器的host name不一样,我们用这个来做机器的哈希值,得到的数据放在这个环上,三台机器插到环上

假设将‘左,33岁’这个信息通过哈希函数,会对应到环上的某个位置,通过顺时针找到最近的机器。

怎样知道是最近的是哪个机器:有逻辑端服务器,是要实现数据分配,三台机器的哈希值排序存放在逻辑服务器

增加机器:通过哈希函数找到对应环上的位置,接管顺时针以前的数据

增加/减小机器数据迁移的代价很明显降低了,但是存在问题: 1.机器数量很少的时候很难做到在环上的均衡,2.即使机器在环上均衡了,但是增加/减少机器时,负载依旧不均衡;

解决方法:虚拟节点技术

m1机器分配1000个字符串a1,a2,..,a1000

m2机器分配1000个字符串b1,b2,..,b1000

m3机器分配1000个字符串c1,c2,..,c1000

虚拟节点去抢环上的位置,m1有1000个代表字符串,每一个字符串计算哈希值去抢环,m2,m3

虚拟节点上的数据迁移,比如说a1000上的数据给b500怎样实现: a1000去m1上找数据,找到之后给m2,作为m2上第500位置的数据

同样的,增加/减少机器m也分配1000个字符串

   

要是m1机器性能较好,我们可以将m1分配的字符串增加到a2000.让它多处理点数据

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值