哈希的应用

news2024/11/16 13:43:12

文章目录

  • 前言
  • 一、位图
    • 1.1位图概念
    • 1.2位图的实现
    • 1.3 位图的应用
  • 二、 布隆过滤器
    • 2.1 布隆过滤器提出
    • 2.2 布隆过滤器概念
    • 2.3 布隆过滤器的插入
    • 2.4 布隆过滤器的哈希函数
    • 2.5 布隆过滤器的查找
    • 2.6 布隆过滤器删除
    • 2.7 布隆过滤器的优点
    • 2.8 布隆过滤器的缺陷
    • 2.9 布隆过滤器的应用场景


前言

本小节带大家了解关于位图和布隆过滤器模拟使用和简单实现。


正文开始

一、位图

1.1位图概念

我们先来引入一个腾讯的面试题,方便我们来了解位图!

给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中。
1.遍历,时间复杂度为O(N).
2.使用二分查找。但是需要先排序,排序的时间复杂度为O(N l o g 2 N log_2N log2N),查找的时间复杂度为O( l o g 2 N log_2N log2N).

但是以上的方法必须要加载到内存中,40亿个整数是16G,内存不能开出连续这么大的空间。

3,位图解决
数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一
个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0
代表不存在。比如:
在这里插入图片描述
我们可以计算这种位图方法需要多少内存去存储呢?

一个整形为4个字节,一个字节等于8个比特位。
所以本来四个字节存一个数,现在四个字节可以存32个数
所以所占内存为16G/32=500MB
空间是不是一下节省了很多呢!!!

所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的。

1.2位图的实现

namespace hulu
{
	//N个比特位的位图
	template<size_t N>
	class bitset
	{
	public:
		bitset()
		{
			//+1保证足够的bit位,最多浪费八个
			_bits.resize(N/8+1,0);
		}
		//x映射的位标记为1
		void set(size_t x)
		{
			//x映射的比特位在第几个char对象
			size_t i = x / 8;
			//x在char的第几个比特位
			size_t j = x%8;
			_bits[i] |= (1 << j);
		}
		//x映射的位标记为0
		void reset(size_t x)
		{
			//x映射的比特位在第几个char对象
			size_t i = x / 8;
			//x在char的第几个比特位
			size_t j = x % 8;
			_bits[i] &= (~(1 << j));
		}
		bool test(size_t x)
		{
			//x映射的比特位在第几个char对象
			size_t i = x / 8;
			//x在char的第几个比特位
			size_t j = x % 8;
			return _bits[i] &(1 << j);
		}
	private:
		vector<char> _bits;

	};
}

在这里插入图片描述
在这里插入图片描述
19也是同理,set之后结果为0c。
在这里插入图片描述

1.3 位图的应用

  1. 快速查找某个数据是否在一个集合中
  2. 排序+去重
  3. 求两个集合的交集和并集等
  4. 操作系统中磁盘块标记

二、 布隆过滤器

2.1 布隆过滤器提出

我们在使用新闻客户端看新闻时,它会给我们不停地推荐新的内容,它每次推荐时要去重,去掉那些已经看过的内容。问题来了,新闻客户端推荐系统如何实现推送去重的? 用服务器记录了用户看过的所有历史记录,当推荐系统推荐新闻时会从每个用户的历史记录里进行筛选,过滤掉那些已经存在的记录。 如何快速查找呢?

  1. 用哈希表存储用户记录,缺点:浪费空间
  2. 用位图存储用户记录,缺点:位图一般只能处理整形,如果内容编号是字符串,就无法处理了。
  3. 将哈希与位图结合,即布隆过滤器

2.2 布隆过滤器概念

布隆过滤器是由布隆在1970年提出的一种紧凑的,比较巧妙的概率性数据结构
特点是高效的插入和查询,可以用来告诉你"某样东西一定不存在或者可能存在",它是用多个哈希函数,将一个数据映射到位图结构中。此种方式不仅可以提升查询效率,也可以节省大量的内存空间

2.3 布隆过滤器的插入

在这里插入图片描述
向布隆过滤器中插入:“baidu”
在这里插入图片描述
"baidu"这个字符串映射了三个比特位,将这三个比特位置1即可。

在插入"tencent"这个字符串
在这里插入图片描述

2.4 布隆过滤器的哈希函数

很显然,过小的布隆过滤器很快所有的 bit 位均为 1,那么查询任何值都会返回“可能存在”,起不到过滤的目的了。布隆过滤器的长度会直接影响误报率,布隆过滤器越长其误报率越小。

另外,哈希函数的个数也需要权衡,个数越多则布隆过滤器 bit 位置位 1 的速度越快,且布隆过滤器的效率越低;但是如果太少的话,那我们的误报率会变高。
在这里插入图片描述

依照大佬计算出来的公式,我们拿来使用!
在这里插入图片描述

k=(m/n)* l n 2 ln_2 ln2

namespace hulu
{
	struct BKDRHash
	{
		size_t operator()(const string& s)
		{
			// BKDR
			size_t value = 0;
			for (auto ch : s)
			{
				value *= 31;
				value += ch;
			}
			return value;
		}
	};
	struct APHash
	{
		size_t operator()(const string& s)
		{
			size_t hash = 0;
			for (long i=0;i<s.size();i++)
			{
				if ((i & 1) == 0)
				{
					hash ^= ((hash << 7) ^ s[i] ^ (hash >> 3));
				}
				else
				{
					hash ^= (~((hash << 11) ^ s[i] ^ (hash >> 5)));
				}
			}
			return hash;
		}
	};
	struct DJBHash
	{
		size_t operator()(const string& s)
		{
			size_t hash = 5381;
			for (auto ch : s)
			{
				hash += (hash << 5) + ch;
			}
			return hash;
		}
	};
	template<size_t M, class K=string,
		class HashFunc1= BKDRHash,
		class HashFunc2= APHash,
		class HashFunc3= DJBHash>
	class BloomFiliter
	{
	public:
		void set(const K& key)
		{
			size_t hash1 = HashFunc1()(key) % M;
			size_t hash2 = HashFunc2()(key) % M;
			size_t hash3 = HashFunc3()(key) % M;
			_bs.set(hash1);
			_bs.set(hash2);
			_bs.set(hash3);
		}
		bool Test(const K& key)
		{
			size_t hash1 = HashFunc1()(key) % M;
			size_t hash2 = HashFunc2()(key) % M;
			size_t hash3 = HashFunc3()(key) % M;
			if (_bs.test(hash1) && _bs.test(hash2) && _bs.test(hash3))
				return true;//可能存在误判
			return false;
		}
	private:
		hulu::bitset<M> _bs;
	};
}

测试代码

	void TestBloomFiliter()
	{
		BloomFiliter<43> bl;
		string a[] = {"苹果","香蕉","梨","西瓜",
			"查找","eeeeeffff","asfasfas",
			"继续","set","桃子"};
		for (auto& e : a)
		{
			bl.set(e);
		}
		for (auto& e : a)
		{
			cout << bl.Test(e) << endl;
		}
		cout << endl;
		cout << bl.Test("ffffeeeee") << endl;
		cout << bl.Test("string") << endl;
		cout << bl.Test("芒果") << endl;
	}

在这里插入图片描述

2.5 布隆过滤器的查找

布隆过滤器的思想是将一个元素用多个和希函数映射到一个位图中,因此被映射的位置的比特位一定为1.所以可以按照一下方式进行查找:**分别计算每个哈希值对应的比特位置存储的是否为零,只要有一个为零,代表该元素一定不在哈希表中,否则可能在哈希表中。
**

注意:布隆过滤器如果说某个元素不存在时,该元素一定不存在;如果该元素存在时,该元素可能存在,因为有一些哈希函数存在一定的误判。

比如:在布隆过滤器中查找"ffffeeeee",假设三个哈希函数计算的哈希值为:1,3,7,刚好和"eeeeeffff"的比特位重叠,此时布隆过滤器告诉该元素存在,但其实该元素是不存在的。

2.6 布隆过滤器删除

比如:删除上图中的"tencent"元素,如果直接将该元素所对应的二进制比特位0,"baidu"元素也被删除了,因为这两个元素在哈希函数计算出的比特位上刚好有重叠。

一种支持删除的方法:,将布隆过滤器中的每个比特位扩展成一个小的计数器,插入元素时给k个计数器(k个哈希函数计算出的哈希地址)+1,删除元素时,给k个计数器-1,通过多占用几倍存储空间的代价来增加删除操作。

缺陷:

  1. 无法确认元素是否真正在布隆过滤器中
  2. 存在计数回绕

注意:布隆过滤器的特点节省空间,支持删除就不那么节省了。

2.7 布隆过滤器的优点

  1. 增加和查询元素的时间复杂度为O(K),(K为哈希函数的个数,一般比较小),与数据量的大小无关。
  2. 哈希函数相互之间没有关系,方便硬件进行计算。
  3. 布隆过滤器不需要存储元素本身,在某些对保密要求比较严格的场合有很大的优势。
  4. 在能承受一定的误判时,布隆过滤器比其他数据结构有着很大的空间优势。
  5. 数据量很大时,布隆过滤器可以表示全集,其他数据结构不能。
  6. 使用同一组散列函数的布隆过滤器可以进行交、并、差运算。

2.8 布隆过滤器的缺陷

  1. 有误判率,即存在假阳性(False Position),既不能准确判断元素是否在集合中(补救方法:再建立一个白名单,存储可能误判的数据)
  2. 不能获取元素本身
  3. 一般情况下不能从布隆过滤器中删除元素
  4. 如果采用计数方式删除,可能会存在计数回绕问题。

2.9 布隆过滤器的应用场景

A.注册的时候,快速判断一个昵称时候使用过?

  1. 不在,没有用过,直接使用
  2. 在,再去数据库确认一遍

B.黑名单

  1. 不在,可以直接通行
  2. 在,再次去系统确认

C. 过滤层,提高查找数据效率


(本章完)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1524.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

散射辐射变送器的优势体现在哪些方面?

散射辐射是经过大气分子、水蒸气、灰尘等质点的散射&#xff0c;改变了方向的太阳辐射&#xff0c;也称天空散射辐射。太阳散射辐射强弱程度与太阳辐射的入射角、大气条件&#xff08;云量、水汽、砂粒、烟尘等粒子的多少&#xff09;和地面反射率有关。当天空的浑浊程度加大&a…

链路状态路由协议 OSPF (三)

作者简介&#xff1a;一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.OSPF领接关系的建立 1.OSPF领接关系的建立概述 &#xff0…

彻底理解Java并发:乐观锁与CAS

本篇内容包括&#xff1a;悲观锁与乐观锁的概述、CAS&#xff08;Compare And Swap&#xff09;比较并交换的介绍、非阻塞算法与ABA问题&#xff0c;以及对 Java 中 CAS 的实现解读&#xff08;AtomicInteger 对 CAS 的实现&#xff0c;Unsafe 类简介&#xff09;。 一、悲观锁…

【树莓派不吃灰】Raspberry Pi上搭建NodeJS运行环境

目录1. 前言2. 安装NodeJS环境2.1 安装npm2.2 安装nodejs2.3 配置NPM国内镜像源3. 总结❤️ 博客主页 单片机菜鸟哥&#xff0c;一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2022-10-28 ❤️❤️ 本篇更新记录 2022-10-28 ❤️&#x1f389; 欢迎关注 &#x1f50e;点赞…

嵌入式C语言编程中经验教训总结(八)变量、指针和指针数组的内存管理

目录嵌入式C语言编程中经验教训总结&#xff08;八&#xff09;变量、指针和指针数组的内存管理变量、指针和指针数组的内存占用指针、指针数组的空间验证指针数组的元素数据访问方法嵌入式C语言编程中经验教训总结&#xff08;八&#xff09;变量、指针和指针数组的内存管理 …

【趣学算法】第一章读书笔记

14天阅读挑战赛 *努力是为了不平庸~ 算法学习有些时候是枯燥的&#xff0c;这一次&#xff0c;让我们先人一步&#xff0c;趣学算法&#xff01; 文章目录1.1打开算法之门1.2 妙不可言——算法复杂性算法的特性好算法的标准时间复杂度和空间复杂度时间复杂度空间复杂度宕机1.4算…

62. 如何通过增强(Enhancement) 的方式给 SAP ABAP 标准程序增添新功能

文章目录 如何找到可以创建增强实现的增强点位置如何创建增强实现如何在 SE80 里找到增强实现本身如何调试 ABAP 增强实现总结ABAP 系统有比较完善的修改控制权限管控,比如笔者试图修改一个 SAP ABAP 系统里标准的函数,就会遇到如下的警告消息,然后修改的尝试会被阻止: You…

Winform和ASP.NET、Web API详解

Winform和ASP.NET、Web API 一、winform基础 1.1 基础学习 1、 winform应用程序是一种智能客户端技术&#xff0c;我们可以使用winform应用程序帮助我们获得信息或者传输信息等。 2、属性 Name:在后台要获得前台的控件对象&#xff0c;需要使用Name属性。 visible:指示一…

认识运营商机房

文章目录走线设备机房走线数据机房走线传输机房列头柜【供电】网络架构ONU设备OLT设备汇聚层交换机BARS设备核心路由器运营商网络架构【必看】铁塔基站核心机房ODF&#xff1a;光纤配线架MME光纤SGWPGWHSS交换机拓扑核心机房拓扑接入层基站&#xff08;BaseStation&#xff09;…

山西大同大学技术会,大同大学的家!

大家好&#xff0c;我是康来个程&#xff0c;山西大同大学技术会的创建者。 低谷时代 近几年校内的竞赛氛围越来越浓厚&#xff0c;随着自身参与并了解的赛事越来越多&#xff0c;随之而来的也是发现了我们学校竞赛方面的问题。疫情原因&#xff0c;我们的比赛取消的取消&…

Gitee在大数据中心的使用

在本地主机或者可以VSCode直接连接可视化的服务器上 1. 首先在gitee新建一个带有develop分支的仓库 2. 在自己的主机&#xff08;e.g., server 1~3&#xff09;上git clone下来&#xff0c;例如 git clone gitgitee.com:PeterBishop0/TransT-based.git 3. 切换成develop分支&…

深度学习入门(十) 模型选择、过拟合和欠拟合

深度学习入门&#xff08;十&#xff09; 模型选择、过拟合和欠拟合前言模型选择例子&#xff1a;预测谁会偿还贷款&#xff1f;训练误差和泛化误差验证数据集和测试数据集K-则交叉验证总结过拟合和欠拟合模型容量模型容量的影响估计模型容量VC维线性分类器的VC维VC维的用处数据…

[云原生之k8s] Kubernetes原理

引言 单机容器编排&#xff1a;docker-compose 容器集群编排&#xff1a;docker swarm、mesosmarathon、kubernetes 应用编排&#xff1a;ansible 一、Kubernetes是什么&#xff1f; Kubernetes的缩写为&#xff1a;K8S&#xff0c;这个缩写是因为k和s之间有八个字符的关系…

线段树模板

好文分享&#xff1a;【数据结构】线段树&#xff08;Segment Tree&#xff09; - 小仙女本仙 - 博客园 线段树和树状数组的基本功能都是在某一满足结合律的操作(比如加法&#xff0c;乘法&#xff0c;最大值&#xff0c;最小值)下&#xff0c;O(logn)的时间复杂度内修改单个元…

Python回归预测建模实战-支持向量机预测房价(附源码和实现效果)

机器学习在预测方面的应用&#xff0c;根据预测值变量的类型可以分为分类问题&#xff08;预测值是离散型&#xff09;和回归问题&#xff08;预测值是连续型&#xff09;&#xff0c;前面我们介绍了机器学习建模处理了分类问题&#xff08;具体见之前的文章&#xff09;&#…

x86 --- 任务隔离特权级保护

程序是记录在载体上的数据和指令。 程序正在执行时的一个副本叫做任务 所有段描述符都放在GDT --> 不做区分。 内核程序&#xff08;任务&#xff09;所占段在GDT中&#xff0c;用户程序&#xff08;任务&#xff09;所占段在LDT中 --> 做区分。 每个任务都有自己独立的…

【无标题】

第1章 概述 本章主要内容&#xff1a; 互联网的概念&#xff08;标准化&#xff09;、组成、发展历程&#xff1b;电路交换的基本概念、分组交换的原理&#xff1b;计算机网络的分类、性能指标及两种体系结构。 重点掌握&#xff1a; 在计算机网络分层模型中&#xff0c;网…

7、GC日志详解

目录如何分析GC日志参数配置程序运行GC日志打印解析GC日志数据分析指定其他垃圾收集器CMSG1GC分析工具JVM参数汇总查看命令如何分析GC日志 参数配置 对于java应用我们可以通过一些配置把程序运行过程中的gc日志全部打印出来&#xff0c;然后分析gc日志得到关键性指标&#xff…

目标检测算法——遥感影像数据集资源汇总(附下载链接)

关注”PandaCVer“公众号 深度学习资料&#xff0c;第一时间送达 目录 一、用于 2-5 分类问题 1.UCAS-AOD 遥感影像数据集 2.Inria Aerial Image Labeling Dataset 3.RSOD-Dataset 物体检测数据集 二、用于 5-10 分类问题 1.RSSCN7 DataSet 遥感图像数据集 2.NWPU…

孙宇晨接受韩国媒体专访:熊市受宏观经济的不确定性影响

10月27日至10月29日&#xff0c;韩国釜山备受关注的大型区块链活动 2022 釜山区块链周&#xff08;BWB 2022&#xff09;在釜山会展中心&#xff08;BEXCO&#xff09;举行。韩国区块链媒体TokenPost 对出席活动的波场TRON创始人孙宇晨进行了专访。10月28日&#xff0c;该媒体发…