C++语法(24) 哈希应用

news2024/11/25 22:37:36

C++语法(23)-- 模拟实现unordered_set和unordered_map_哈里沃克的博客-CSDN博客icon-default.png?t=N4P3https://blog.csdn.net/m0_63488627/article/details/130449452?spm=1001.2014.3001.5501 

目录

1.位图

1.定义

2.实现

3.应用

4.特点

2.布隆过滤器

1.介绍

2.设计场景

3.实现

4.应用


1.位图

1.定义

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

2.实现

要求:给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中。

构造函数的实现:由于有N个数,而char可以存储8位的信息,那么最后有N/8个,不过由于除法会切割后面的多余,所以我们需要对N/8+1处理。


求出在哪一个char中:size_t i = x / 8;
求出在char的哪一位上:size_t j = x % 8;

插入的逻辑(或上1左移j位):_bits[i] |= (1 << j);

删除的逻辑(和上1左移j位后取非):_bits[i] &= (~(1 << j));

判断是否在的逻辑:return _bits[i] & (1 << j); 没有则返回0,找到返回非零

namespace MY
{
	template<size_t N>
	class bit_set
	{
	public:
		bit_set(size_t N)
		{
			_bits.resize(N / 8 + 1, 0);
		}

		void set(size_t x)
		{
			size_t i = x / 8;
			size_t j = x % 8;

			_bits[i] |= (1 << j);
		}

		void reset(size_t x)
		{
			size_t i = x / 8;
			size_t j = x % 8;

			_bits[i] &= (~(1 << j));
		}

		bool text(size_t x)
		{
			size_t i = x / 8;
			size_t j = x % 8;

			return _bits[i] & (1 << j);
		}
	private:
		vector<char> _bits;
	};
}

3.应用

其实位图的使用很灵活,我们不是非要一个数对应一个比特位这么狭隘;我们可以根据需求,定义一个数对应比特位的多少,;或许用多个位图一起使用,这样就能实现更广的范围。

1. 给定100亿个整数,设计算法找到只出现一次的整数?

我们可以定义两个位:00为0次,01为1次,10为1以上。这样就能实现。

当然使用两个位图也可以实现。


2. 给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?

两个先去重,随后用两个位图,如果都有数据说明是交集。


3. 位图应用变形:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数
我们可以定义两个位:00为0次,01为1次,10为2次,11为3次以及以上。只需要找01和10即可满足要求。

4.特点

优点:1.节省空间 2.快

缺点:1.一半需要数据比较集中,如果过于分散,空间的消耗会增大 2.只针对整型

2.布隆过滤器

1.介绍

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

2.设计场景

1.注册昵称不允许出现重复的,布隆过滤器用于昵称的查重

2.黑名单列表

3.实现

1.不能实现删除,以为过滤器特殊的误判机制

2.set就是将hashFunc得到的结果映射到位图中,将所有的Func得到位图的结果都进行判1处理

3.test,将所有hash值对应的位图的数据找到,如果没有在位图中说明该数据一定没有出现,如果找到,说明有可能出现误判,那么具体后续的处理还需要设计

4.高效率的设置为:HashFuncN=(N/X)*ln2

HashFuncN:Func函数有几个

N:数据的多少

X:位图的大小

namespace MY
{
	struct BKDRHash
	{
		size_t operator()(const string& key)
		{
			size_t hash = 0;
			for (auto ch : key)
			{
				hash *= 131;
				hash += ch;
			}
			return hash;
		}
	};

	struct APHash
	{
		size_t operator()(const string& key)
		{
			unsigned int hash = 0;
			int i = 0;

			for (auto ch : key)
			{
				if ((i & 1) == 0)
				{
					hash ^= ((hash << 7) ^ (ch) ^ (hash >> 3));
				}
				else
				{
					hash ^= (~((hash << 11) ^ (ch) ^ (hash >> 5)));
				}

				++i;
			}

			return hash;
		}
	};

	struct DJBHash
	{
		size_t operator()(const string& key)
		{
			unsigned int hash = 5381;

			for (auto ch : key)
			{
				hash += (hash << 5) + ch;
			}

			return hash;
		}
	};

	struct JSHash
	{
		size_t operator()(const string& s)
		{
			size_t hash = 1315423911;
			for (auto ch : s)
			{
				hash ^= ((hash << 5) + ch + (hash >> 2));
			}
			return hash;
		}
	};

	//HashFuncN=(N/X)*ln2
	template<size_t N , 
		size_t X = 6,
		class K = string, 
		class HashFunc1 = BKDRHash, 
		class HashFunc2 = APHash, 
		class HashFunc3 = DJBHash,
		class HashFunc4 = JSHash>
	class BloomFilter
	{
	public:
		bool set(const K& key)
		{
			size_t hash1 = HashFunc1()(key) % (X * N);
			size_t hash2 = HashFunc2()(key) % (X * N);
			size_t hash3 = HashFunc3()(key) % (X * N);
			_bs.set(hash1);
			_bs.set(hash2);
			_bs.set(hash3);
			return true;
		}

		bool test(const K& key)
		{
			size_t hash1 = HashFunc1()(key) % (X * N);
			if (!_bs.test(hash1))
			{
				return false;
			}
			size_t hash2 = HashFunc2()(key) % (X * N);
			if (!_bs.test(hash2))
			{
				return false;
			}
			size_t hash3 = HashFunc3()(key) % (X * N);
			if (!_bs.test(hash3))
			{
				return false;
			}

			return true;//可能会出现重复的误判
		}

	private:
		std::bitset<N * X> _bs;
	};
}

误判率高,空间开的多就能解决。不过过分追求误判率的低会导致开辟的空间消耗过大。

4.应用

1. 给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分别给出
精确算法和近似算法

近似算法:对其中一个文件放入布隆过滤器,另一个进行比较。找出来的交集比真正的交集多,以为会出现误判。

精确算法:假设每个文件的query为50byte,100亿个query有500G。将两个大文件分别切分,按照哈希思路映射(/1000)到单位为0.5G的小文件Ai,Bi。A0文件对应B0文件...A999文件对应B999文件,取出一对文件,两个文件去重后再进行取交集,依次找就能得到精确的交集。


2. 如何扩展BloomFilter使得它支持删除元素的操作

其实很简单,之所以不行是因为我们设计的位图只表示存在不存在,因此只有01表示,删除就会出现误判。那么我们只需要设计可以计数的布隆过滤器就能解决可以删除的问题。不过设计出支持删除的布隆过滤器就意味着开辟一个巨大的空间,有时候空间消耗太大反而不值当的。

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

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

相关文章

STM32F407输入捕获

文章目录 F407定时器输入捕获实验支持输入捕获的定时器有哪些输入捕获工作过程输入捕获测量高电平脉宽原理滤波器设置 配置步骤开启TIM5时钟与端口时钟配置PA0为用能复用功能&#xff08;AF2&#xff09;初始化端口并开启下拉电阻初始化TIM5设置TIM5的输入捕获参数TIM_Channel通…

数字信号处理10:Z变换(2)

今天我就不写后面的Z变换的剩下的东西了&#xff0c;直接写代码&#xff1a; 说实话&#xff0c;Python的Scipy.signal里面是没有和matlab一样的ztrans和iztrans&#xff0c;这让我头疼了几天时间&#xff0c;但是后面&#xff0c;看文档的时候&#xff0c;突然发现&#xff0…

Vue2模拟贪吃蛇小游戏

目录 一、效果展示 二、代码展示 三、原理讲解 3.1、页面创建 3.2、创建蛇与食物 3.3、移动与边界判断 3.4、吃、得分总结 二、代码展示 view的本地文件&#xff1a;可直接运行。 <template><div class"game"><div class"game-div"…

【架构基础】SOLID原则

SOLID原则是一套坚实而有效的软件设计原则&#xff0c;它由Robert C. Martin&#xff08;也称为 Uncle Bob&#xff09;在2000年提出&#xff0c;旨在帮助软件开发者设计出高内聚低耦合的软件&#xff0c;构建易于测试、可维护和可扩展的软件系统&#xff0c;降低软件后期的维护…

青春永不散场

虽然人生总是在不断的离别与相遇&#xff0c;但请相信这一次的离别是为了下次更美好的相遇。 一.毕业感想 四年的大学生活即将画上句号&#xff0c;让我不由得感慨万千。这四年里&#xff0c;我经历了无数的挑战和机遇&#xff0c;也结交了一群志同道合的朋友&#xff0c;收获…

抖音小程序+抖音矩阵系统开发:新玩法,新趋势

抖音seo优化源码&#xff0c;抖音seo矩阵系统搭建&#xff0c;抖音账号矩阵系统开发&#xff0c;企业在做账号矩阵过程中&#xff0c;最头疼的莫过于私域线索转化&#xff0c;作为开发者都知道&#xff0c;目前市面上我们了解的矩阵系统除了挂载POI信息外&#xff0c;无法挂载留…

【剑指offer】旋转数组的最小数字

文章目录 题目思路代码实现 题目 题目链接入口&#xff1a;JZ11 旋转数组的最小数字 思路 1.核心考点 &#xff08;1&#xff09;数组理解&#xff0c;二分查找&#xff0c;临界条件。 2.解题思路 &#xff08;1&#xff09;题目要求查找出一维数组的最小值&#xff0c;本…

变分模态分解(VMD)学习

目录 概述构造变分问题变分求解问题(引入拉格朗日)关于变分构造中的函数理解关于Uk(t)关于希尔伯特变换关于频谱调制 VMD算法(python) 概述 变分模态分解由Konstantin Dragomiretskiy于2014年提出&#xff0c;可以很好抑制EMD方法的模态混叠现象&#xff08;通过控制带宽来避免…

信息竞赛笔记(2)––快速幂

目录 快速幂 定义 分析 代码 递归实现 非递归实现(通用方法) 模意义下取幂 快速幂 定义 快速幂,二进制取幂(Binary Exponentiation,也称平方法),是一个在的时间内计算的小技巧&#xff0c;而暴力的计算需要的时间。 这个技巧也常常用在非计算的场景&#xff0c;因为它可…

【论文】通过基准分析优化联邦人员重新识别的性能

论文链接 目录 摘要1. 绪论2. 相关工作2.1 人员重新识别2.2 联邦学习 3. 联邦 个人REID基准3.1 数据集3.2 联合方案3.3 模型结构3.4 联邦学习算法3.5 性能指标3.6 参考实现4.1 通过相机联合方案4.2 按数据集联合方案 5. 性能优化5.1 知识蒸馏5.2 权重调整5.3 知识蒸馏和体重调…

提高代码质量的秘诀:类、方法、字段和包注释

&#x1f9d1;‍&#x1f4bb;CSDN主页&#xff1a;夏志121的主页 &#x1f4cb;专栏地址&#xff1a;Java基础进阶核心技术专栏 目录 &#x1f362; 一、注释的插入 &#x1f363; 二、类注释 &#x1f364; 三、方法注释 &#x1f365; 四、字段注释 &#x1f96e; 五、…

GreenPlum集群部署之抽丝剥茧

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

【stable diffusion原理解读通俗易懂,史诗级万字爆肝长文,喂到你嘴里】

文章目录 一、前言&#xff08;可跳过&#xff09;二、stable diffusion1.clip2.diffusion modelforward diffusion &#xff08;前向扩散&#xff09;逆向扩散&#xff08;reverse diffusion&#xff09;采样图阶段小结 3.Unet modeltimestep_embedding采用正余弦编码 三、sta…

华为OD机试真题 Java 实现【求符合要求的结对方式】【2023Q1 100分】,附详细解题思路

一、题目描述 用一个数组A代表程序员的工作能力&#xff0c;公司想通过结对编程的方式提高员工的能力&#xff0c;假设结对后的能力为两个员工的能力之和&#xff0c;求一共有多少种结对方式使结对后能力为N。 二、输入描述 6 2 3 3 4 5 1 6 第一行为员工的总人数&#xff…

精简总结:一文说明软件测试基础概念

基础概念-1 基础概念-2 目录 一、什么是软件测试&#xff1f; 二、软件测试的特点 三、软件测试和开发的区别 1、内容&#xff1a; 2、技能区别 3、工作环境 4、薪水 5、发展前景 6、繁忙程度 7、技能要求 四、软件测试与调试的区别 1、角色 2、目的 3、执行的阶…

Lecture 7 Deep Learning for NLP: Feedforward Networks

目录 Deep LearningFeedforward Neural Network 前馈神经网络Neuron 神经元Output Layer 输出层OptimizationRegularization 正则化Topic Classification 主题分类Language Model as Classifiers 语言模型作为分类器Word Embeddings 词嵌入Training a Feed-Forward Neural Netw…

RVOS操作系统协作式多任务切换实现-03

RVOS操作系统协作式多任务切换实现-03 任务&#xff08;task&#xff09;多任务 &#xff08;Multitask&#xff09;任务上下文&#xff08;Context&#xff09;多任务系统的分类协作式多任务 创建和初始化第 1 号任务切换到第一号任务执行协作式多任务 - 调度初始化和任务创建…

虚拟机-安装与使用2023

虚拟机-安装与使用 前言 一、虚拟机 1.VMware 2.Virtualbox 二、VMware 的下载 三、VMware 的安装 四、验证是否安装成功 五、运行 VMware 六、VMware 上安装其它操作系统 安装 Windows 10安装 CentOS-Linux安装 Kali-Linux 七、VMware 常用功能同步时间系统备份克隆快照内存设…

黑马Redis视频教程高级篇(多级缓存案例导入说明)

目录 一、安装MYSQL 1.1、准备目录 1.2、运行命令 1.3、修改配置 1.4、重启 二、导入SQL 三、导入Demo工程 3.1、分页查询商品 3.2、新增商品 3.3、修改商品 3.4、修改库存 3.5、删除商品 3.6、根据id查询商品 3.7、根据id查询库存 3.8、启动 四、导入商品查询…

Maven高级——私服(完结撒花!)

作用与介绍 一个公司内有两个项目组&#xff0c;如果其中一个开发了一个依赖tlias-utils,另一个项目组要使用的话要么就是传过来直接install放到自己的本地仓库里面的。 但是也可以搭建一个公共仓库&#xff0c;专门供公司局域网内部使用&#xff0c;也就是所谓私服。 然后在…