C++——哈希3|位图

news2024/11/29 13:51:44

 

目录

常见哈希函数

位图

位图扩展题 

位图的应用


 

常见哈希函数

 1. 直接定址法--(常用)

这种方法不存在哈希冲突
取关键字的某个线性函数为散列地址:Hash(Key)= A*Key + B
优点:简单、均匀
缺点:需要事先知道关键字的分布情况
使用场景:适合查找比较小且连续的情况
面试题:字符串中第一个只出现一次字符

只出现一次的字符串


2. 除留余数法--(常用)

存在哈希冲突,重点解决哈希冲突
设散列表中允许的地址数为m,取一个不大于m,但最接近或者等于m的质数p作为除数,
按照哈希函数:Hash(key) = key% p(p<=m),将关键码转换成哈希地址


3. 平方取中法--(了解)
假设关键字为1234,对它平方就是1522756,抽取中间的3位227作为哈希地址;
再比如关键字为4321,对它平方就是18671041,抽取中间的3位671(或710)作为哈希地址
平方取中法比较适合:不知道关键字的分布,而位数又不是很大的情况


4. 折叠法--(了解)
折叠法是将关键字从左到右分割成位数相等的几部分(最后一部分位数可以短些),然后将这
几部分叠加求和,并按散列表表长,取后几位作为散列地址。
折叠法适合事先不需要知道关键字的分布,适合关键字位数比较多的情况


5. 随机数法--(了解)
选择一个随机函数,取关键字的随机函数值为它的哈希地址,即H(key) = random(key),其中
random为随机数函数。
通常应用于关键字长度不等时采用此法


6. 数学分析法--(了解)
设有n个d位数,每一位可能有r种不同的符号,这r种不同的符号在各位上出现的频率不一定
相同,可能在某些位上分布比较均匀,每种符号出现的机会均等,在某些位上分布不均匀只
有某几种符号经常出现。可根据散列表的大小,选择其中各种符号分布均匀的若干位作为散
列地址。

位图

 面试题
给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在
这40亿个数中。【腾讯】

这里用搜索树和哈希表都不行,搜索树还有left,right,colour有额外空间,哈希表有next指针消耗,这俩种方式都会消耗空间导致内存中存不下

排序+二分查找 同样数据太大,只能放在磁盘上,磁盘上不好支持二分查找 
1. 遍历,时间复杂度O(N)
2. 排序(O(NlogN)),利用二分查找: logN
3. 位图解决
数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一
个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0
代表不存在。比如:

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


 用位图的方式,这里大概占用512MB

 按位开空间不好开,我们按char开空间,一个char占一个字节,一个字节是8个比特位

 标记为1的方法,把1进行左移或右移,之后进行按位或

 reset和set相反,reset//计算出来位置后,把那个位置标记为0,其它位标记为1

test:判断x在不在,这一位和1相与判断在不在


	template<size_t N>//N个比特位,
	class bitset
	{
	public:
		bitset()
			:
		{
			_bits.resize(N / 8+1, 0);//如果N对8能整除就N/8,不能对8整除就+1多开一个字节,这种浪费比较少可忽略
             
		}
		void set(size_t x)//计算在第几个char的第几个位,如20,20/8=2在第二个char,20%8=4第四个比特位
		{
			size_t i = x / 8;
			size_t j = x % 8;
			//计算出来位置后,把那个位置标记为1
			_bits[i] |= (1 << j);
		}
		void reset(size_t x)//让这位变为0,其它位是1
		{
			size_t i = x / 8;
			size_t j = x % 8;
			//计算出来位置后,把那个位置标记为0,其它位标记为1
			_bits[i] &= ~(1 << j);
		}
		bool test(size_t x)//判断x在不在
		{
			size_t i = x / 8;
			size_t j = x % 8;
			return _bits[i] & (1 << j);
		}
	private:
		vector<char> _bits;
	};

 走到8的时候,第二个char显示16进制的1,说明8是第二个char的第一个比特位,是全体的第8个比特位

第9位是3,说明是第二个char的第二个比特位,因为要和前面8所表示的1加起来

 

上面40亿的数据进行位图计算,此时会溢出,-1是无符号的-1

 

改为这种写法就不会报错 ,大概占用是512MB

 当执行完之后,内存被释放,这是因为这里是vector有自己的析构,不需要我们写

位图扩展题 

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

kv的统计次数搜索模型,我们使用位图,俩个比特位表示一个值,大概需要一个G

 

 我们依靠上面的代码,搞俩个位图,俩个位图相对应的位置表示一个值出现次数

	template<size_t N>//N个比特位,
	class bitset
	{
	public:
		bitset()
			:
		{
			_bits.resize(N / 8+1, 0);//如果N对8能整除就N/8,不能对8整除就+1多开一个字节,这种浪费比较少可忽略
             
		}
		void set(size_t x)//计算在第几个char的第几个位,如20,20/8=2在第二个char,20%8=4第四个比特位
		{
			size_t i = x / 8;
			size_t j = x % 8;
			//计算出来位置后,把那个位置标记为1
			_bits[i] |= (1 << j);
		}
		void reset(size_t x)//让这位变为0,其它位是1
		{
			size_t i = x / 8;
			size_t j = x % 8;
			//计算出来位置后,把那个位置标记为0,其它位标记为1
			_bits[i] &= ~(1 << j);
		}
		bool test(size_t x)//判断x在不在
		{
			size_t i = x / 8;
			size_t j = x % 8;
			return _bits[i] & (1 << j);
		}
	private:
		vector<char> _bits;
	};
	template<size_t N>
	class twobitset
	{
	public:
		void set(size_t x)
		{
			bool inSet1 = _b1s1.test(x);
			bool inSet2 = _b1s2.test(x);
			if (inset1 == false&&inset2==false)//如果之前x不存在,我们此时传参传的是x,set就由00->01
			{
				//00->01
				_bs2.set(x);
			}
			else if (inset1 == false && inset2 == true)//如果之前x是01,我们此时传参传的是x,set就由01->10
			{
				//01->10
				_bs1.set(x);
				_bs2.reset(x);
			}
			//如果之前x是10,我们就不用管了
		}
	private:
		bitset<N> _bs1;
		bitset<N> _bs2;
	};
}

 测序程序,这里只打印了出现一次的数据。

void test_bit_set3()
{
	int a[] = { 3, 4, 5, 2, 3, 4, 4, 4, 4, 12, 77, 65, 44, 4, 44, 99, 33, 33, 33, 6, 5, 34, 12 };

	myspace::twobitset<100> bs;
	for (auto e : a)
	{
		bs.set(e);
	}

	bs.print_once_num();
}
}

 

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

    找交集,使用俩个位图,第一个集合对应第一个位图,第二个集合对应第二个位图,如果既在位图1又在位图2,则是交集,或者俩个位图进行与,映射位都是1的就是交集

  2. 位图应用变形:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数

    这里需要四种状态00(0次),01(1次),10(2次),11(3次及以上)

     位图缺点:只能处理整数

  3. 位图的优点:快,节省空间

位图的应用

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

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

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

相关文章

C语言学习笔记(八): 自定义数据类型

结构体变量 什么是结构体 C语言允许用户自己建立由不同类型数据组成的组合型的数据结构&#xff0c;它称为结构体 结构体的成员可以是任何类型的变量&#xff0c;如整数&#xff0c;字符串&#xff0c;浮点数&#xff0c;其他结构体&#xff0c;指针等 struct Student //s…

streamlit自定义组件教程和组件开发环境配置

About create your own component&#xff1a; you can follow this tutorial streamlit tutorial 重要&#xff01;以下步骤都是在教程的基础上更改的。这个教程做的很棒。 Component development environment configuration&#xff1a; 根据文章 https://streamlit-com…

【iOS】APP IM聊天框架的设计(基于第三方SDK)

【iOS】APP IM聊天框架的设计&#xff08;基于第三方SDK&#xff09; 前言 在开发社交聊天类型的APP的时候&#xff0c;IM是必不可少的功能&#xff0c;而且很多公司的IM服务都是接的第三方的&#xff0c;很少用自研的&#xff0c;国内的IM厂商也都很成熟&#xff0c;本文所有…

基于文心大模型套件ERNIEKit实现文本匹配算法,模块化方便应用落地

文心大模型,产业级知识增强大模型介绍 官网:https://wenxin.baidu.com/ 文心大模型开发套件ERNIEKit,面向NLP工程师,提供全流程大模型开发与部署工具集,端到端、全方位发挥大模型效能。 提供业界效果领先的ERNIE 3.0系列开源模型和基于ERNIE的前沿任务模型,满足企业和开…

暴力破解(new)

数据来源 本文仅用于信息安全的学习&#xff0c;请遵守相关法律法规&#xff0c;严禁用于非法途径。若观众因此作出任何危害网络安全的行为&#xff0c;后果自负&#xff0c;与本人无关。 01 暴力破解介绍及应用场景 》暴力破解介绍 》暴力破解字典 GitHub - k8gege/Passwor…

QT(56)-动态链接库-windows-导出变量-导出类

1.导出变量 1.1不使用_declspec(dllimport) _declspec(dllexport) 使用_declspec(dllimport) _declspec(dllexport) 1.2win32 mydllwin32 myexe 1.3win32 mydllqt myexe 2.导出类 使用_declspec(dllimport) _declspec(dllexport) 2.1不用关键…

导出Excel表格(调用后端接口方式)

在开发中我们会遇到导出Excel表格的需求&#xff0c;但是导出分为前端生成和后端生成。前端生成的方式CSDN其他小伙伴已经做出了很多教程&#xff0c;是依赖xlsx插件。但是&#xff0c;今天我讲的是&#xff0c;调用后端接口的方式生成Excel表格。1.调用后端提供的导出接口&…

Doris--简单使用

一、数据表的创建与数据导入 1.1、创建表 1.1.1、单分区 CREATE TABLE table1 (siteid INT DEFAULT 10,citycode SMALLINT,username VARCHAR(32) DEFAULT ,pv BIGINT SUM DEFAULT 0 -- 聚合模型&#xff0c; value column 使用sum聚合 ) AGGREGATE KEY(siteid, citycode, …

【Java】二叉树

一、树形结构 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的。它具有以下的特点&#xff1a; 有一个特殊…

IDEA安装ChatGPT插件

ChatGPT&#xff0c;美国OpenAI [1] 研发的聊天机器人程序 [12] &#xff0c;于2022年11月30日发布 [2-3] 。ChatGPT是人工智能技术驱动的自然语言处理工具&#xff0c;它能够通过学习和理解人类的语言来进行对话&#xff0c;还能根据聊天的上下文进行互动&#xff0c;真正像人…

mybatis条件构造器(一)

mybatis条件构造器(一) 1 准备工作 1.1 建表sql语句(Emp表) SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0; -- ---------------------------- -- Table structure for emp -- ---------------------------- DROP TABLE IF EXISTS emp; CREATE TABLE emp (EMPNO int NOT N…

tws耳机哪个牌子音质好?tws耳机音质排行榜

随着蓝牙耳机市场的不断发展&#xff0c;使用蓝牙耳机的人也逐渐增多&#xff0c;近年来更是超越有线耳机成为最火爆的数码产品之一。那么&#xff0c;tws耳机哪个牌子音质好&#xff1f;下面&#xff0c;我来给大家推荐几款音质好的tws耳机&#xff0c;可以当个参考。 一、南…

vb 模块和作用域的关系

模块在VB中有三种类型的模块&#xff0c;分别是窗体模块、标准模块和类模块。窗体模块窗体模块中包含了窗体以及窗体中所有控件的事件过程&#xff0c;文件扩展名为&#xff08;*.frm)&#xff0c;窗体文件中不仅包含窗体对象的外观设计&#xff0c;也包含窗体模块&#xff08;…

基于matlab评估星载合成孔径雷达性能

一、前言本示例展示了如何评估星载合成孔径雷达 &#xff08;SAR&#xff09; 的性能&#xff0c;并将理论极限与 SAR 系统的可实现要求进行比较。SAR利用雷达天线在目标区域上的运动来提供更精细的方位角分辨率。给定雷达的主要参数&#xff08;例如工作频率、天线尺寸和带宽&…

Nginx配置Https协议(告别Http协议,使用Https)图

注&#xff1a; 相关代码&#xff1a;Linux部署Nginx&#xff08;快速&#xff09;_Dyansts的博客-CSDN博客 视频教程 &#xff1a;6分钟告别http协议&#xff0c;使用更加安全的https协议_哔哩哔哩_bilibili 细节 免费申请ssl网站&#xff1a;FreeSSL首页 - FreeSSL.cn一…

OpenShift 4 - 将 VMware 虚机迁移至 OpenShift Virtualization(视频)- 冷迁移

《OpenShift / RHEL / DevSecOps 汇总目录》 说明&#xff1a;本文已经在支持 OpenShift 4.12 的 OpenShift 环境中验证 文章目录环境说明OpenShift Virtualization 环境VMware vSphere 环境了解 Migration Toolkit for Virtualization安装 Migration Toolkit for Virtualizati…

教你使用内嵌chatGPT的新必应(bing)

巨头们的AI战愈演愈烈起来。在谷歌公布其 ChatGPT 竞品Bard后的第二天&#xff0c;微软就官宣了两款新的 AI 产品&#xff1a;基于下一代 OpenAI 大型语言模型上的新版 Bing 搜索引擎&#xff0c;号称“比 ChatGPT 更强大”&#xff0c;以及基于 AI 功能的改进版 Edge 网络浏览…

在 Flutter 中使用 webview_flutter 4.0 | js 交互

大家好&#xff0c;我是 17。 已经有很多关于 Flutter WebView 的文章了&#xff0c;为什么还要写一篇。两个原因&#xff1a; Flutter WebView 是 Flutter 开发的必备技能现有的文章都是关于老版本的&#xff0c;新版本 4.x 有了重要变化&#xff0c;基于 3.x 的代码很多要重…

亲历华为手机丢失通过定位找回

我有个华为Meta 40E手机&#xff0c;用了一年半左右。前天&#xff0c;也就是周六上午去小区超市买菜&#xff0c;顺便遛遛狗。 回来的路上在红色的步行道&#xff0c;可乐和糯米&#xff08;我家养的两只边牧犬&#xff09;看到前面不远处有几只流浪的小狗&#xff0c;就叫着…

如何查询IPv4归属地信息呢?

想查询IPv4归属地&#xff0c;首先要知道自己的IP地址是什么。下面&#xff0c;我将介绍IP地址查询方法和IPv4归属地查询方法。一、查局域网IP地址方法第一种方法&#xff1a;通过命令行窗口获取内网IP地址1.打开命令行窗口。使用开始菜单中的搜索功能搜索“cmd ”,并以管理员身…