前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【C++】位图

【C++】位图

作者头像
平凡的人1
发布于 2023-10-15 04:19:15
发布于 2023-10-15 04:19:15
17300
代码可运行
举报
运行总次数:0
代码可运行

位图概念

boss直接登场:

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

40亿个整数,大概就是16GB。40亿个字节大概就是4GB。

1Byte=8bit 1KB=1024Byte 1MB=1024KB=1024*1024=1048576字节 1GB=1024MB=1024*1048576≈10亿字节,所以4GB约等于40亿字节 1TB=1024GB

如果采用排序+二分的做法来查找:排序要用到数组,要开出16GB大的数组,排在数组里才能进行二分查找,但是这些数组在内存里放不下,所以排序都排不了。那只能放到磁盘上,那数据在磁盘上就不能用二分了,不支持下标,效率也慢

如果用红黑树和哈希表:数组都存放不下,红黑树和哈希表更不用说了,红黑树三叉链结构+颜色,消耗更大,哈希表也有消耗:存放_next指针,负载因子等问题,内存放不下。

下面,我们解决这个问题的方法是位图

这个问题是在不在的问题,是key的模型,那我们可以标记在还是不在,我们只需要一个比特位就可以标记在还是不在

数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0代表不存在

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


位图操作

位图核心的三个操作是setresettest

set是将x对应的比特位置设为1,reset是将x对应的比特位置设为0,test用来查看x在不在

set将对应的比特位置设为1:_bits[i]|=(1<<j) reset将对应的比特位置设为0:_bits[i]&=(~(1<<j)) test查看x在或不在:_bits[i]&(1<<j)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        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 test(size_t x)
		{
			size_t i = x / 8;
			size_t j = x % 8;
			return _bits[i] & (1 << j);
		}

位图代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#pragma once
#include <iostream>
#include <vector>
using namespace std;

namespace hwc
{
	template<size_t N>
	class bitset
	{
	public:
		bitset()
		{
			_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 test(size_t x)
		{
			size_t i = x / 8;
			size_t j = x % 8;
			return _bits[i] & (1 << j);
		}
	private:
		vector<char> _bits;
	};

	void test_bitset()
	{
		//bitset<100> bs1;
		//bitset<-1> bs2;//
		bitset<0xffffffff> bs2;
		bs2.set(10);
		bs2.set(20);
		bs2.set(3000);
		cout << bs2.test(10) << endl;
		cout << bs2.test(20) << endl;
		cout << bs2.test(3000) << endl;
		cout << bs2.test(666) << endl;
		cout << bs2.test(777) << endl << endl;
		bs2.reset(20);
		bs2.set(666);
		cout << bs2.test(10) << endl;
		cout << bs2.test(20) << endl;
		cout << bs2.test(3000) << endl;
		cout << bs2.test(666) << endl;
		cout << bs2.test(777) << endl;
	}
}

小细节:(-1)的size_t类型

实际上,库里面也有位图:


位图应用

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

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

100亿个数字找到只出现一次的整数,这是KV模型的统计次数,数字有三种状态:0次、1次、1次以上,。这三种状态需要用两个比特位就可以表示,分别位00代表0次,01代表1次,10代表1次以上既可以。我们可以采用两个位图来实现,复用上面所实现的位图即可解决问题

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template<size_t N>
	class twobitset
	{
	public:
		void set(size_t x)
		{
			if (!_bs1.test(x) && !_bs2.test(x))//00
			{
				_bs2.set(x);//01
			}
			else if (!_bs1.test(x) && _bs2.test(x))//01
			{
				_bs1.set(x);
				_bs2.reset(x);//10
			}
			//10不变
		}
		void PrintOnce()
		{
			for (size_t i = 0; i < N; ++i)
			{
				if (!_bs1.test(i) && _bs2.test(i))
				{
					cout << i << endl;
				}
			}
			cout << endl;
		}
	private:
		bitset<N> _bs1;
		bitset<N> _bs2;
	};

	void test_twobitset()
	{
		twobitset<100> tbs;
		int a[] = { 2,3,4,56,99,55,3,3,2,2,10 };
		for (auto e : a)
		{
			tbs.set(e);
		}
		tbs.PrintOnce();
	}

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

1 个文件有 100 亿个 int,1G内存,设计算法找到出现次数不超过2次的所有整数

这与上面的类似,多判断一次把10->11,最后找不超过两次的整数

给一个超过100G大小的log file,log中存着IP地址,设计算法找到出现次数最多的IP地址

统计次数自然是要map的,map有附带消耗,三叉链。位图只能判断在不在。所以还是要用map统计的: 我们可以把整个文件通过哈希切分成小的文件,然后去进行统计次数,但是如果小的文件超过1G,说明了这个小文件有两种情况: 1.这个小文件冲突的ip很多,但都是不同的ip,map统计不下------->map的insert插入失败,没有内存,相当于new节点失败,new失败会抛出异常 2.这个肖文杰冲突的ip很多,大多都是相同的ip,map可以统计-------->直接用map统计,可以统计,不会报错

位图特点:位图只能处理整形。采用位图标记字符串时,必须先将字符串转化为整形的数字,找到位图对应的比特位置

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-03-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
【DB宝60】PG12高可用之1主2从流复制环境搭建及切换测试
PostgreSQL在9.x之后引入了主从的流复制机制,所谓流复制,就是备服务器通过tcp流从主服务器中同步相应的数据,主服务器在WAL记录产生时即将它们以流式传送给备服务器,而不必等到WAL文件被填充。
AiDBA宝典
2021/07/29
3.3K0
【DB宝61】PostgreSQL使用Pgpool-II实现读写分离+负载均衡
官网:https://www.pgpool.net/mediawiki/index.php/Main_Page
AiDBA宝典
2021/07/29
2.9K0
【DB宝95】PG 14 + Pgpool-II + Watchdog 实现高可用(自动故障转移+读写分离+负载均衡)
Pgpool-II是一个在PostgreSQL服务器和PostgreSQL数据库客户端之间工作的中间件。它是根据BSD许可证授权的。它提供以下功能。
AiDBA宝典
2022/04/11
4K3
【DB宝95】PG 14 + Pgpool-II + Watchdog 实现高可用(自动故障转移+读写分离+负载均衡)
【DB宝91】PG高可用之主从流复制+keepalived 的高可用
通过keepalived 来实现 PostgreSQL 数据库的主从自动切换,以达到高可用。当主节点宕机时,从节点可自动切换为主节点,继续对外提供服务。
AiDBA宝典
2022/02/23
2.9K0
【DB宝91】PG高可用之主从流复制+keepalived 的高可用
5、pgpool-II高可用性(一)数据库的高可用性
使用 pgpool-II 软件;我们常用来实现流复制的高可用性;备库只读的,不可写;就是当主库出现问题时;需要把备库自动激活为主库;来接管服务。
huofo
2022/03/18
2K0
PG高可用之repmgr(1主2从+1witness)+Pgpool-II实现主从切换+读写分离+负载均衡
第二次执行时不再提示输入yes,并且可以成功执行命令,则表示SSH对等性配置成功。
AiDBA宝典
2022/11/07
3K0
PG高可用之repmgr(1主2从+1witness)+Pgpool-II实现主从切换+读写分离+负载均衡
【DB宝62】PG高可用之repmgr(1主2从+1witness)+Pgpool-II实现主从切换+读写分离+负载均衡
第二次执行时不再提示输入yes,并且可以成功执行命令,则表示SSH对等性配置成功。
AiDBA宝典
2021/07/29
1.8K1
pgpool-II 4.3 中文手册 - 入门教程
在本节中,我们假设您已经安装了 Pgpool-II 与 PostgreSQL 集群。
为少
2022/05/17
1.8K0
pgpool-II 4.3 中文手册 - 入门教程
原 利用pgpool实现PostgreSQL的高可用
基于流复制的方式,两节点自动切换:     1、单pgpool         a.环境: pgpool:192.168.238.129 data1:192.168.238.130 data2:192.168.238.131         b.图例         c.配置互信 ssh-copy-id ha@node1 ssh-copy-id ha@node2         d.数据库节点配置,请参照《 使用pg_basebackup搭建PostgreSQL流复制环境 》。
王果壳
2018/06/21
2.3K0
进阶数据库系列(十九):PostgreSQL 基于 Pgpool 实现读写分离
Pgpool 是一个高性能的连接池和负载均衡器,用于 PostgreSQL 数据库。Pgpool 可以作为中间层,位于客户端和 PostgreSQL 服务器之间,来管理连接请求并分配给不同的 PostgreSQL 服务器进行处理,以提高整体的系统性能和可用性。Pgpool 的一些主要功能包括:
民工哥
2023/08/22
4.1K0
进阶数据库系列(十九):PostgreSQL 基于 Pgpool 实现读写分离
PG-Pool-II 读写分离使用体验
设置连接数控制,避免过高的连接导致访问报错,当超出连接数上线后,对后续的访问进行排队等待。
腾讯云数据库 TencentDB
2021/09/03
1.8K0
PG-Pool-II 读写分离使用体验
「在 Kubernetes 上运行 Pgpool-Il」实现 PostgreSQL 查询(读)负载均衡和连接池
因为 PostgreSQL 是一个有状态的应用程序,并且管理 PostgreSQL 有非常具体的要求(例如备份、恢复、自动故障转移等),Kubernetes 的内置功能无法处理这些任务。因此,需要一个扩展 Kubernetes 功能以创建和管理 PostgreSQL 的 Operator。
为少
2022/03/31
1.8K0
「在 Kubernetes 上运行 Pgpool-Il」实现 PostgreSQL 查询(读)负载均衡和连接池
PostgreSQL体系结构
原文:https://www.enmotech.com/web/detail/1/764/1.html
数据和云01
2019/07/31
1.1K0
PostgreSQL体系结构
史上最全PostgreSQL体系结构
墨墨导读:本文主要从日志文件、参数文件、控制文件、数据文件、redo日志(WAL)、后台进程这六个方面来讨论PostgreSQL的结构。
数据和云
2019/07/22
4.1K0
史上最全PostgreSQL体系结构
使用 Bitnami PostgreSQL Docker 镜像快速设置流复制集群
使用以下环境变量,可以使用 Bitnami PostgreSQL Docker 镜像 轻松设置流复制集群:
为少
2022/05/17
1.6K0
使用 Bitnami PostgreSQL Docker 镜像快速设置流复制集群
使用Bucardo搭建PG的双主
https://www.xmmup.com/shiyongogg-for-pgweifuwukuaisushuangxiangtongburdsshujukushuangzhu.html
AiDBA宝典
2023/04/26
2K0
使用Bucardo搭建PG的双主
PostgreSQL主备库搭建
yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
雪人
2022/10/13
2.7K0
搭建一个高可用的镜像仓库,这是我见过最详细、最简单的教程
大家好,我是小碗汤,今天分享一篇搭建一个高可用镜像仓库的教程。详细中夹杂着简单~。篇幅较长,兄弟们不妨耐心看完~
我的小碗汤
2022/01/14
1.7K0
搭建一个高可用的镜像仓库,这是我见过最详细、最简单的教程
PostgresSQL 主从搭建步骤
由于工作需要,最近开始接触各种数据库,并尝试各种数据库产品的高可用方案。今天分享的是postgresSQL的主从配置,其实还是蛮简单的,跟随本文的步骤,保证能实现PG主从的搭建。
星哥玩云
2022/08/13
2.5K0
在docker中快速使用各个版本的PostgreSQL数据库(9.4、9.6、10、11、12、13、14、15等)
PG安装方法很多,和MySQL类似,给用户提供很大的选择空间。如:RPM包安装(在线、离线)、源码编译安装、系统自带、二进制、NDB安装等。
AiDBA宝典
2023/09/08
4.8K0
在docker中快速使用各个版本的PostgreSQL数据库(9.4、9.6、10、11、12、13、14、15等)
推荐阅读
相关推荐
【DB宝60】PG12高可用之1主2从流复制环境搭建及切换测试
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档