哈希函数和哈希表

哈希函数的重要特征
1.输入为无限的值 输入为有限集合
2.相同的输入会有相同的输出
3.不同的输入也可能会出现不同的输出(哈希碰撞 概率极低)
4.获得的值是离散且平均的 就是说 在固定区域类获得的hash返回结果是平均的
加入我们返回值是在1-100之间,那么输入10000个数 得到的结果 为1 或者其他的数量都基本相同,几乎是10个。
一道题:给我们40亿个数,想要求出出现次数最多的值,要求规定内存是1G,我们会对这个40亿个数求哈希值,然后%100,得到的结果就是在0,99之间,而且离散均匀分布 就是说 每个值上分布的个数几乎一致,然后求出每个里面个数最多的,然后最后凑出100个再进行比较 得出最多的:在这里插入图片描述

哈希表:在这里插入图片描述

  1. 设计RandomPool,有如下功能,insert,delete,getRandom,其中的getRandom可以等概率的获取数。要求所有操作时间复杂度为O(1);

只有删除操作稍微麻烦一点,需要我们将最后一位填报上删除掉的位置即可。

public class RandomPool{
	public static void main(String[] args){
		Pool<String> pool=new Pool();
		pool.insert("g");
		pool.insert("s");
		pool.insert("x");
		System.out.println(pool.getRandom());
	}
	
	private static class Pool<T>{
		private HashMap<T,Integer> map1=new HashMap();//里面装的是字符串 和它对应的索引
		private HashMap<Integer,T> map2=new HashMap();//里面装的是索引 和它对应的字符串
		private int size=0;
		
		public T getRandom(){//随机返回一个
			if(size==0){
				return null;
			}
			int index=(int)(Math.random() * size);//随机获取的索引值
			return map2.get(index);
		}
		
		public void insert(T key){
			map1.put(key, size);
			map2.put(size++, key);
		}
		
		public void delete(T key){
			if(map1.containsKey(key)){
				int index1=map1.get(key);
				map1.put(map2.get(size-1), index1);
				map1.remove(key);
				map2.put(index1, map2.get(size-1));
				map2.remove(--size);
			}
		}
	}
	
}
  1. 布隆过滤器,我们在了解这个之前先看一看位图:
//位图
public class BitMap {
	int arr[]=new int[10];//10个int类型的数组就是 32字节 * 10 = 320bit  320位 可以代表320个状态信息
	
	//获取某一位的信息 比如170位
	public int getNum(int num){
		int index=num/32;//首先是数组的第几个位置
		int n=num%32;//然后是那个位置的第几个字节
		return (arr[index]>>n) & 1;//将这个数据右移n位 让该位的数跑到字的最右边的位置 和 1取& 得到当前位是1 还是0
	}
	
	//将某一位的信息修改为1
	public void changeToOne(int num){
		int index=num/32;
		int n=num%32;
		arr[index]=arr[index]|(1<<n);//将我们1左移到 该位上 然后取或操作 将这个位置上的值修改为1
	}
	
	public void changeToZero(int num){
		int index=num/32;
		int n=num%32;
		arr[index]= arr[index]& ~(1<<n);//将我们的1左移到该位置上 然后取反 其他位置全为1 该位置为0 两个取&操作 会将该位置转换为0
	}
}

我们的布隆过滤器是干什么的,主要是用于网站黑名单的过滤,一个浏览器有很多url的黑名单,上亿种,如果我们用字符串来存储的话,会耗费几百个G的内存,但如果放在外存里面又很耗时。此时我们就用位图来标记:
1.首先创建一个长度为m位的数组(1字节=8位)
2.然后我们拿到这个网站的url,对它做k种不同的Hash操作,做完后将他进行对m的取余运算,得到的值,在数组种对应位置标记为1,每次操作得到的结果都将对应位置标记为1.
3.当我们想要判断一个url是否是黑名单中的,直接进行k中不同的Hash操作,然后对m进行取余运算,得到的值在数组中寻找是否所有的位置都为1,如果都为1那么它就是黑名单中的url。
这样操作就是我们的布隆过滤器的操作,这样的操作更加节省空间,但是会有失误。
一共存在两种失误:1.将白名单中的url误判为黑名单中的url 2.将黑名单中的url误判为白名单的url
我们的布隆过滤器只会存在第一种失误 因为可能会存在某一个url进行k中hash计算后对m取模结果和黑名单中的一致(哈希碰撞),导致判断失误。
但是这种失误是可以通过我们的设计来减少的,合理的设计m的大小,和k种操作的大小能够减少失误。m应该稍微大一点,k也应该大一点,这样能够减少不同url出现相同值的可能性,但是k不能太大,太大会导致我们的m会很轻易的被填满,然后造成更多的失误。

布隆过滤器的数值的计算公式:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值