位图的实现,布隆过滤器

2023-09-21 12:59:27

位图:

概念:

由于位图是通过一个比特位来判断是不是在范围里面的,所以其对应的时间复杂度都是O(1)的。

位图的实现:

如上图所示:
上图对应的就是3个字节,即24个比特位

要想实现位图,就得知道我们要记录的这个数应该存储到哪个位置,假设这个数是x

那么对应:

x / 32 所得的值就是该数字应该存在第几个字节上

x % 32 所得的值就是对应在此字节的第几位上,这样一来位图就简单了

我们主要实现 set,reset,test这三个借口,代码如下:

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

namespace bit
{
	template<size_t N>
	class bitset
	{
	public:

		bitset()
		{
			_a.resize(N / 32 + 1);
		}

		// x映射的那个标记成1
		void set(size_t x)
		{
			size_t i = x / 32;
			size_t j = x % 32;

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

		// x映射的那个标记成0
		void reset(size_t x)
		{
			size_t i = x / 32;
			size_t j = x % 32;

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

		// 判断 x 是否在位图里面
		bool test(size_t x)
		{
			size_t i = x / 32;
			size_t j = x % 32;

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

	private:
		vector<int> _a;
	};
}

注意这里模板的应用,是为了开出大小适中的位图出来。

测试代码:

位图的应用:

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

要找到只出现一次的整数,就要让出现一次和出现多次的数有所区别,

而位图只能存储0或1,所以没法区别,这是就需要用到两个位图:

只要出现多次,就将其记成10,这样就得以区分

对应的代码实现:

template<size_t N>
	
	class TwoBitSet1
	{
	public:
		void set(size_t x)
		{
			// 00 -> 01
			if (!_bs1.test(x) && !_bs2.test(x))
			{
				_bs2.set(x);
			}

			//01 -> 10
			else if (!_bs1.test(x) && _bs2.test(x))
			{
				_bs1.set(x);
				_bs2.reset(x);
			}
		}

		bool is_once(size_t x)
		{
			return !_bs1.test(x) && _bs2.test(x);
		}

	private:
		bitset<N> _bs1;
		bitset<N> _bs2;
	};

测试代码:

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

解法:

将两个文件分别映射到两个位图,再将两个位图的值与一下即可:

对应的代码实现如下:

int main()
{
	int a1[] = { 1, 2, 3, 3, 4, 4, 4, 4, 4, 2, 3, 6, 3, 1, 5, 5, 8, 9 };
	int a2[] = { 8, 4, 8, 4, 1, 1, 1, 1 };

	bit::bitset<10> bs1;
	bit::bitset<10> bs2;

	for (auto e : a1)
	{
		bs1.set(e);
	}

	for (auto e : a2)
	{
		bs2.set(e);
	}

	for (int i = 0; i < 10; i++)
	{
		if (bs1.test(i) && bs2.test(i))
		{
			cout << i << " ";
		}
	}
	cout << endl;
	return 0;
}

代码测试:

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

其实做法与第一题很像,直接上代码:

template<size_t N>

	class TwoBitSet2
	{
	public:
		void set(size_t x)
		{
			// 00 -> 01
			if (!_bs1.test(x) && !_bs2.test(x))
			{
				_bs2.set(x);
			}

			//01 -> 10
			else if (!_bs1.test(x) && _bs2.test(x))
			{
				_bs1.set(x);
				_bs2.reset(x);
			}
			//10 -> 11
			else if (_bs1.test(x) && !_bs2.test(x))
			{
				_bs2.set(x);
			}
		}

		bool is_once(size_t x)
		{
			return !_bs1.test(x) && _bs2.test(x);
		}

		bool is_twice(size_t x)
		{
			return _bs1.test(x) && !_bs2.test(x);
		}



	private:
		bitset<N> _bs1;
		bitset<N> _bs2;
	};

测试代码:

库里面的位图接口:

布隆过滤器:

概念:

只能确定其一定不存在或者可能存在,注意可能二字

所以说布隆过滤器不能准确判断一个东西是否存在。

应用:

1.不需要精确的场景,快速判断昵称是否存在

2.精确的场景,布隆过滤器

更多推荐

Java 字节流

一、输入输出流输入输出-------读写文件输入-------从文件中获取数据到自己的程序中,接收处理【读】输出-------将自己程序中处理好的数据保存到文件中【写】流-------数据移动的轨迹二、流的分类按照数据的移动轨迹分为:输入流输出流按照每一次读写/数据量的大小将流分成:字节流字符流字节流:每一次可读写一个

使用Canvas绘制一个验证码组件

使用Canvas绘制一个验证码组件前言验证码,这一日常伴随我们的要素,是我们在线交互的重要安全保障。你的手机短信里是否被它占据半壁江山,今天我们就来聊聊如何在网页上实现一个简单的验证码组件。大家在登录网站时为了防止被恶意攻击或者多次点击操作,使用验证码是最常用的实现方式。在学习完Canvas后,通过Canvas实现简单

Linux管理多版本node.js

这里介绍的是Linux版本的nvm工具:一个nodejs版本管理工具!这里可以灵活切换node指定版本哟~下载地址:https://github.com/nvm-sh/nvm/releases/1.安装需要先安装git、curlyuminstall-ygitcurl这里很慢,需要登录。如果不小心退出来,需要重新执行一下

AI绘画Stable Diffusion原理之扩散模型DDPM

前言传送门:stablediffusion:Git|论文stable-diffusion-webui:GitGoogleColabNotebook部署stable-diffusion-webui:GitkaggleNotebook部署stable-diffusion-webui:GitAI绘画,输入一段文本就能生成相关

xyhcms getshell

下载xyhcms3.6.2021版本并用phpstudy搭建functionget_cookie($name,$key=''){if(!isset($_COOKIE[$name])){returnnull;}$key=empty($key)?C('CFG_COOKIE_ENCODE'):$key;$value=$_CO

Naivcat 数据迁移工具 | 竟然那么香

近期,我们收到一位童鞋的留言(如下图),他建议我们多宣传Navicat的数据迁移工具,因为他身边许多小伙伴并非很了解这一功能。今天,我们为大家深度介绍Naivcat安全、可靠的数据迁移工具。请童鞋们准备好NavicatPremium工具,我们马上开始!数据库数据迁移是指选择、准备、提取和转换数据,并将数据从一个计算机存

孩子写作业买什么样台灯合适?适合孩子读写台灯推荐

现在孩子的普遍都存在视力问题,而导致孩子近视的原因可能跟光线太强或太弱、不用的用眼习惯、长时间的过度用眼等因素有关,根据数据表明目前中国近视患者人数达到6亿多,其中儿童青少年的视力不良率甚至高达八成,所以在孩子的学习道路上,护眼也是重中之重的事情。平时间养成良好的用眼习惯是必不可少的,不过照明光源的选择也重要,所以挑选

树莓派4b装系统到运行 Blazor Linux 本地程序全记录

在Linux下运行gui程序,咱也是第一次做,属于是瞎子过河乱摸一通,写得有什么不对和可以优化的地方,希望各位看官斧正斧正.##1.下载烧录器https://www.raspberrypi.com/software/####我选择的是Raspbian64位系统,并配置好ssh账号密码,wifi,以便启动后可以直接黑屏s

贪心算法(Greedy Algorithm)

贪心算法(GreedyAlgorithm)是一种解决优化问题的算法策略。在贪心算法中,每一步都会选择当前情况下最优的选择,而不考虑未来的后果。贪心算法的基本思想是通过局部最优选择达到全局最优。它并不保证一定能得到全局最优解,但在某些情况下可以得到近似最优解或者符合要求的解。贪心算法的适用条件是问题具有"最优子结构"和"

Web自动化测试进阶 —— Selenium模拟鼠标操作

鼠标操作事件在实际的web产品测试中,对于鼠标的操作,不单单只有click(),有时候还要用到右击、双击、拖动等操作,这些操作包含在ActionChains类中。ActionChains类中鼠标操作常用方法:首先导入ActionChains类:fromselenium.webdriver.common.action_c

2023年9月21日,历史上的今天大事件早读

​公元前19年9月21日古罗马诗人维吉尔逝世1069年9月21日宋神宗采用王安石新法,开始实行青苗法1643年9月21日皇太极逝世1898年9月21日慈禧太后发动戊戌政变1909年9月21日我国飞机设计师冯如第一次试飞成功1920年9月21日民主革命家朱执信遇难1926年9月21日荷兰物理学家昂内斯首次发现物理超导性1

热文推荐