哈希表——位图

news2025/1/24 5:36:50

哈希表——位图

  • 基本概念
  • 一道面试题
  • 位图实现
    • 设置存在或不存在
    • 检查存在
  • 解决一开始的问题

之前我们已经了解了哈希表的底层实现,今天我们来了解一下哈希表思想的衍生产物——位图

基本概念

在了解位图之前,我们先来了解一些简单的概念。
我们都知道,计算机的数据和指令都是二进制的:
在这里插入图片描述二进制里面只有0,1两个数字,这就意味着这两个数字可以表示两个不同的状态,位图的基础也是基于这一点。

所以,我们利用这一点。假设我们现在有一堆海量的数据,我可以通过某种方式让数字对应到相应的二进制的数位上,同时规定0表示该数字不存在,1表示存在。这本质上也是一种哈希的思想。

在这里插入图片描述

一道面试题

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

如果我们硬来,先将这40亿个数存起来,然后二分查找。这无疑是不行的。因为,光是把数据存起来就要用掉16GB的内存,而且要求空间连续。

在这里插入图片描述
但是这时候我们用位图,让位图的每一位对应一个数字,1表示存在,0表示不存在。这样可以大大降低内存的消耗:
在这里插入图片描述
大概我们想要是这样的:
在这里插入图片描述我们所有的位是用来映射存在关系的。

位图实现

我们先来搭搭架子:

#pragma once
#include<iostream>
#include<vector>
using namespace std;

namespace My_bitmap
{
	//N是需要多少bit位
	template<size_t N>
	class bitmap
	{
	public:

	private:
		vector<int> _bmp;
	};
}

现在我们来计算需要多少内存,然后通过构造函数,开出来相应的空间:

#pragma once
#include<iostream>
#include<vector>
using namespace std;

namespace My_bitmap
{
	//N是需要多少bit位
	template<size_t N>
	class bitmap
	{
	public:
		bitmap()
		{
			_bmp.resize(N / 32 + 1, 0); //开出相对应的空间,初始化所有位均为0
		}

	private:
		vector <int> _bmp;
	};
}

设置存在或不存在

现在我们有一个数假设为241,我们要把它设置到位图中,将相应的位设置为1。

因为我们以32位为一组,我们把241 / 32 ,可以得到241被分到了哪一个组,然后241 % 32 的到的是241在第几组的第几位:

在这里插入图片描述
现在我们找到了相应的位置,现在我们要将这个位从0变成1,表示241已经存在,但是我们不能影响其他位的状态,这个时候我们要想起来我们的位运算:
我们来实现一下:
在这里插入图片描述

		bool set(size_t x)
		{
			size_t i = x / 32;
			size_t j = x % 32;

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

好了,我们现在完成了设置,但是现在我想把它又变为0,表示241又不存在了,该怎么办呢?

其实大同小异:
在这里插入图片描述

		bool unset(size_t x)
		{
			size_t i = x / 32;
			size_t j = x % 32;

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

检查存在

检查存在和设置存在其实都差不多,只不过把或换成了与:

		bool check(size_t x)
		{
			size_t i = x / 32;
			size_t j = x % 32;

			return _bmp[i] & (1 << j);
		}

我们来测试一下:

#include"bitmap.h"

int main()
{
	My_bitmap::bitmap<10000> _bt;

	_bt.set(241);
	cout << "是否存在:" << _bt.check(241) << endl;
	_bt.unset(241);
	cout << "是否存在:" << _bt.check(241) << endl;

	return 0;
}

在这里插入图片描述

解决一开始的问题

现在我们封装好了一个位图,但是我们只是解决了数据的储存,我们还没有解决如何只找出出现一次的数。

其实我们发现,这里面有三种状态:一次都没有出现的,出现一次,出现一次及其以上

我们发现,这也表示状态,这样我们可以用我们上面位图再封装一个位图,这个位图用来寻找只出现了一次的数:

要表示三种状态,我们需要两个位图:
在这里插入图片描述

	//N是需要多少bit位
	template<size_t N>
	class twobit_map
	{
	public:
		void set(size_t x)
		{
			if (_bt1.check(x) == false && _bt2.check(x) == false)
			{
				_bt2.set(x);
			}
			else if (_bt1.check(x) == false && _bt2.check(x) == true)
			{
				_bt1.set(x);
				_bt2.unset(x);
			}
		 }

		void Print()
		{
			for (size_t i = 0; i < N; i++)
			{
				if (_bt1.check(i) == false && _bt2.check(i) == true)
					cout << "出现一次:" << i << endl;
			}
		}
	private:
		bitmap<N> _bt1;
		bitmap<N> _bt2;
	};

测试一下:

	My_bitmap::twobit_map<241> _bt;

	int a[] = { 12,34,45,67,12,90,90,45 };

	for (auto e : a)
	{
		_bt.set(e);
	}

	_bt.Print();

在这里插入图片描述我们依次类推,还可以找出出现了一次和两次的数:

	template<size_t N>
	class twobit_map
	{
	public:
		void set(size_t x)
		{
			if (_bt1.check(x) == false && _bt2.check(x) == false)
			{
				_bt2.set(x);
			}
			else if (_bt1.check(x) == false && _bt2.check(x) == true)
			{
				_bt1.set(x);
				_bt2.unset(x);
			}
			else if (_bt1.check(x) == true && _bt2.check(x) == false)
			{
				_bt2.set(x);
			}
		 }

		void Print()
		{
			for (size_t i = 0; i < N; i++)
			{
				if (_bt1.check(i) == false && _bt2.check(i) == true)
					cout << "出现一次:" << i << endl;
				else if (_bt1.check(i) == true && _bt2.check(i) == false)
					cout << "出现两次" << i << endl;
			}
		}
	private:
		bitmap<N> _bt1;
		bitmap<N> _bt2;
	};

这样,我们可以灵活运用位图完成数据的查找,对于40亿的数据我们只需要开足够大的空间即可:

My_bitmap::twobit_map<0xffffff> _bt;

或者

My_bitmap::twobit_map<-1> _bt;

不过这个方法的保证自己写的代码中都使用的是无符号数,不然会有一点问题。

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

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

相关文章

电视盒子什么牌子好?老烧实测2024电视盒子排行榜

电视盒子价格不贵&#xff0c;但功能丰富&#xff0c;看点播、直播&#xff0c;玩游戏&#xff0c;上网课等都不在话下&#xff0c;对大部分家庭来说电视盒子是必备的。不过面对众多产品的时候我们都不知道电视盒子什么牌子好&#xff0c;我是多年电视盒子老用户了&#xff0c;…

比较可相交4点结构迭代次数的顺序

( A, B )---6*30*2---( 1, 0 )( 0, 1 ) 让网络的输入只有6个节点&#xff0c;AB训练集各由6张二值化的图片组成&#xff0c;让差值结构有4个点&#xff0c;收敛误差7e-4&#xff0c;收敛199次&#xff0c;统计迭代次数平均值并排序。 如果行和列可以自由的变换&#xff0c;4个…

【大厂AI课学习笔记】【2.2机器学习开发任务实例】(2)房屋价格预测模型搭建

下面学习一个具体的实例&#xff0c;关于中介根据历史房屋价格&#xff0c;进行房价评估和预测的方法。 大家都知道&#xff0c;中介要给房东和客户报价&#xff0c;一般人是比较有经验的&#xff0c;资深的经纪人&#xff0c;往往会报出更符合市场的价格&#xff0c;再进行一…

谷达冠楠电商:现在开网店能赚钱吗

随着互联网技术的迅猛发展&#xff0c;电子商务已成为现代商业的重要组成部分。许多人纷纷涉足网店经营&#xff0c;希望通过线上渠道实现创业梦想。然而&#xff0c;“现在开网店能赚钱吗?”这个问题的答案并不是绝对的&#xff0c;而是取决于多种因素。 网络市场的低门槛和广…

JWT登录验证前后端设计与实现笔记

设计内容 前端 配置全局前置路由守卫axios拦截器登录页面和主页 后端 JWT的封装登录接口中间件放行mysql数据库的连接 详细设计 路由设计 配置全局前置守卫&#xff0c;如果访问的是登录页面则放行&#xff0c;不是则进入判断是否有token&#xff0c;没有则拦截回到登录…

一连三部电影撤出春节档,给行业带来什么启示?

继《我们一起摇太阳》后&#xff0c;《红毯先生》于2月16日晚也宣布退出今年春节档。 至此&#xff0c;加上动画电影《黄貔&#xff1a;天降财神猫》&#xff0c;2024年春节档已有三部影片撤档&#xff0c;在春节档历届过往中实属少见。 其中&#xff0c;《红毯先生》、《我们…

安装配置NMon

NMon&#xff08;Nigel’s Monitor&#xff09;是一款由IBM公司提供的免费性能监控工具&#xff0c;专门用于监控AIX系统和Linux系统的资源使用情况 下载软件 wget http://sourceforge.net/projects/nmon/files/nmon16p_binaries.tar.gz 如果报错的话&#xff0c;安装提示添加…

论文阅读_用模型模拟记忆过程

英文名称: A generative model of memory construction and consolidation 中文名称: 记忆构建和巩固的生成模型 文章: https://www.nature.com/articles/s41562-023-01799-z 代码: https://github.com/ellie-as/generative-memory 作者: Eleanor Spens, Neil Burgess&#xff…

Python算法100例-1.7 最佳存款方案

完整源代码项目地址&#xff0c;关注博主私信’源代码’后可获取 1.问题描述2.问题分析3.算法设计4.完整的程序 1&#xff0e;问题描述 假设银行一年整存零取的月息为0.63%。现在某人手中有一笔钱&#xff0c;他打算在今后5年中的每年年底取出1000元&#xff0c;到第5年时刚…

matlab代码--基于stbc编码的MIMO-OFDM系统的误码率分析

1 前言 空时分组编码STBC&#xff08;Space Time Block Coding&#xff09;用在无线通信中传输一个数据流的多个拷贝。通过许多天线来产生数据的多种接收版本&#xff0c;提高数据传输的可靠性。接收机接收到的数据拷贝中&#xff0c;存在一些比其它拷贝“更好”的拷贝。而这种…

04 SS之JWT和base64

1.1 jwt和token 1.1.1 token介绍 令牌&#xff08;Token&#xff09;&#xff1a;在计算机领域&#xff0c;令牌是一种代表某种访问权限或身份认证信息的令牌。它可以是一串随机生成的字符或数字&#xff0c;用于验证用户的身份或授权用户对特定资源的访问。普通的令牌可能以…

【动态规划】【C++算法】2742. 给墙壁刷油漆

作者推荐 【数位dp】【动态规划】【状态压缩】【推荐】1012. 至少有 1 位重复的数字 本文涉及知识点 动态规划汇总 LeetCode2742. 给墙壁刷油漆 给你两个长度为 n 下标从 0 开始的整数数组 cost 和 time &#xff0c;分别表示给 n 堵不同的墙刷油漆需要的开销和时间。你有…

多行重定向,expect,字符串处理,高级变量,脚本工具

一&#xff0c;多行重定向 &#xff08;一&#xff09;含义 使用I/O重定向的方式将命令列表提供给交互式程序 标准输入的一种替代品 Here Document 是标准输 入的一种替代品&#xff0c;可以帮助脚本开发人员不必使用临时文件来构建输入信息&#xff0c;而是直接就地 生产出…

Unity类银河恶魔城学习记录7-6 P72 Bouncy sword源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili Sword_Skill_Controller.cs using System.Collections; using System.Colle…

Github 2024-02-18 开源项目日报 Top10

根据Github Trendings的统计&#xff0c;今日(2024-02-18统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量Python项目5PowerShell项目1Rust项目1PHP项目1Jupyter Notebook项目1TypeScript项目1 Black&#xff1a;不妥…

力扣51. N 皇后(回溯)

Problem: 51. N 皇后 文章目录 题目描述思路解决方法复杂度Code 题目描述 思路 1.决策路径&#xff1a;board中小于row的那些行都已经成功放置了皇后&#xff1b; 2.选择列表&#xff1a;第row行的所有列都是放置皇后的选择&#xff08;则根据N皇后相互攻击的股则编写判断当前决…

JVM常见问题笔记分享

文章目录 1 JVM组成1.1 JVM由那些部分组成&#xff0c;运行流程是什么&#xff1f;1.2 什么是程序计数器&#xff1f;1.3 你能给我详细的介绍Java堆吗?元空间(MetaSpace)介绍 1.4 什么是虚拟机栈1.5 堆和栈的区别1.6 能不能解释一下方法区&#xff1f;1.5.1 概述1.5.2 常量池1…

鸿蒙应用模型开发-更新SDK后报错解决

更新SDK后提示 “ohos.application.Ability”/“ohos.application.AbilityStage”等模块找不到或者无相关类型声明 问题现象 更新SDK后报错“Cannot find module ‘ohos.application.AbilityStage’ or its corresponding type declarations”&#xff0c;“Cannot find modu…

【springboot+vue项目(十五)】基于Oauth2的SSO单点登录(二)vue-element-admin框架改造整合Oauth2.0

Vue-element-admin 是一个基于 Vue.js 和 Element UI 的后台管理系统框架&#xff0c;提供了丰富的组件和功能&#xff0c;可以帮助开发者快速搭建现代化的后台管理系统。 一、基本知识 &#xff08;一&#xff09;Vue-element-admin 的主要文件和目录 vue-element-admin/ |…

裁员不可怕,可怕的是软件测试行业在发生巨变,而你却原地踏步

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…