哈希应用之位图+布隆过滤器

news2024/12/23 9:23:54

文章目录

    • bitset介绍
    • bitset常用函数
    • 位图的简单实现
    • 布隆过滤器
    • 布隆过滤器实现

bitset介绍

在 C++ 中,std::bitset 是一个标准库提供的类模板,用于表示固定大小的位集合。std::bitset 类模板允许你以一种方便且高效的方式处理位(二进制位)的集合。它在编译时指定了位集合的大小,并提供了一系列位操作函数,如设置位、清除位、翻转位等。每个位都被映射为一个布尔值,可以被访问和操作。std::bitset 的大小是固定的,由模板参数决定。你需要在创建 std::bitset 对象时指定位集合的大小。例如std::bitset<8>表示一个 8 位的位集合,其中每个位都可以被设置为 0 或 1。std::bitset 提供了方便的接口来进行位级别的操作,例如将多个位集合按位与、按位或、按位取反等。此外,它还提供了一些成员函数来查询位集合的状态和属性,例如测试某个位是否被设置、计算位集合中置位(值为 1 的位)的个数等。

bitset的大小在编译时就需要确定

1. #include<bitset<bitste>>

2.std::bitset<4> foo(5);//用整数初始化  5二进制位:101  foo值:0101 当整数的大小超过位数时,从整数二进制的低位开始赋值,高位被舍弃

3.std::bitset<4> foo;//创建一个4位的位集,每一位默认为0,当整数的大小小于位数时,高位填充为0

4.std::bitset<4> foo(19);//用整数初始化,19二进制位:10011     foo值:0011
5.std::bitset<4> foo(std::string("0101")); //字符串初始化,字符串中必须只能含有‘0’/‘1’

在进行有参构造时,若参数的二进制表示比bitset的size小,则在前面用0补充(如上面的栗子);

若比bitsize大,参数为整数时取后面部分,参数为字符串时取前面部分(比如下面这个李子):

1. #include<bitset<bitste>>

2.bitset<2> bitset1(12);  //12的二进制为1100(长度为4),但bitset1的size=2,只取后面部分,即00

3.string s = "100101";  
  bitset<4> bitset2(s);  //s的size=6,而bitset的size=4,只取前面部分,即1001

4. char s2[] = "11101";
   bitset<4> bitset3(s2);  //与bitset2同理,只取前面部分,即1110

cout << bitset1 << endl;  //00
cout << bitset2 << endl;  //1001
cout << bitset3 << endl;  //1110

bitset常用函数

位运算都可以用: 与、或、非、异或,左移,右移
foo&foo2
    
foo|foo2
    
~foo
    
foo^foo2
    
foo<<=2
    
foo>>=2
    
foo.size()      返回大小(位数)
foo.count()     返回1的个数
foo.any()       返回是否有1
foo.none()      返回是否没有1
foo.set()       全都变成1
foo.set(p)      将第p + 1位变成1
foo.set(p, x)   将第p + 1位变成x
foo.reset()     全都变成0
foo.reset(p)    将第p + 1位变成0
foo.flip()      全都取反
foo.flip(p)     将第p + 1位取反
foo.to_ulong()  返回它转换为unsigned long的结果,如果超出范围则报错
foo.to_ullong() 返回它转换为unsigned long long的结果,如果超出范围则报错
foo.to_string() 返回它转换为string的结果
	bitset<8> foo ("10011011");

    cout << foo.count() << endl;  //5  (count函数用来求bitset中1的位数,foo中共有5个1
    cout << foo.size() << endl;   //8  (size函数用来求bitset的大小,一共有8位

    cout << foo.test(0) << endl;  //true  (test函数用来查下标处的元素是0还是1,并返回false或true,此处foo[0]为1,返回true
    cout << foo.test(2) << endl;  //false  (同理,foo[2]为0,返回false

    cout << foo.any() << endl;  //true  (any函数检查bitset中是否有1
    cout << foo.none() << endl;  //false  (none函数检查bitset中是否没有1
    cout << foo.all() << endl;  //false  (all函数检查bitset中是全部为1

位图的简单实现

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

bitset能实现对数字的位的操作,同时也能通过类似于数组的下标来访问各个位的数值,以执行相应的操作。模拟bitset就是用一个普通的数组来存储数据以达到模拟的目的。

如果我们以一个整型作为比特位的容器,那么如果要求0~N范围的比特位,就需要有N/32+1 个整型来容纳这些比特位,同理如果以char为容器,则需要N/8+1个char来容纳N个比特位。这里我们用vector数组作为底层容纳比特位的容器,且其存储的数据类型为int。

#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <bitset>

using namespace std;

namespace zxy
{
	template<size_t N>   //N表示需要几个比特位
	class bitset
	{
	public:
		bitset()
		{
			_bs.resize(N % 32 + 1, 0);  //计算当前需要几个int + 1
		}
		void set(size_t x)
		{
			size_t i = x / 32;  //计算当前的x在第几个整型
			size_t j = x % 32;  //计算在这个整型的第几个位置上
			//将对应的第i个整型的第j为改成1
			_bs[i] |= (1 << j);
		}

		void reset(size_t x)
		{
			size_t i = x / 32;  //计算当前的x在第几个整型
			size_t j = x % 32;  //计算在这个整型的第几个位置上
			//将对应的第i个整型的第j为改成0
			_bs[i] &= ~(1 << j);
		}

		bool test(size_t x)
		{
			//检测当前x代表的那一bit位是否是1 / 0
			size_t i = x / 32;  //计算当前的x在第几个整型
			size_t j = x % 32;  //计算在这个整型的第几个位置上
			return _bs[i] & (1 << j);
		}
	private:
		vector<int> _bs;
	};
}

布隆过滤器

位图有使用起来,节省空间,并且效率高的优点。位图的缺点,只能处理整形。
假如起昵称时要看一个字符串有没有被占用,用一个bit位标识。哈希解决冲突时,可以把后续同样位置冲突的元素的挂起来,形成链表。但是现在,如果要用位图存储字符串,bit位存不了指针,挂不起来,处理不了哈希冲突。如果用哈希存储又会浪费空间。
因此能不能考虑将哈希和位图结合针对字符串等非整形的类型,设计一个像位图一样的判断key在不在的节省空间的数据结构呢?可以——布隆过滤器
布隆过滤器是一种紧凑的、巧妙的概率型数据结构,能够高效插入查询,来判断一个元素在或不在,用多个哈希函数,把一个数据映射到位图中,不仅能提高查询效率,还能节省空间

在这里插入图片描述

布隆过滤器实现

成员只需要一个位图即可


//N表示需要多少比特位
template<size_t N, class K = string,
	     class HashFunc1 = HashBKDR, 
		 class HashFunc2 = HashAP,  
		 class HashFunc3 = HashDJB>
class BloomFilter
{
public:
	void Set(const K& key)
	{
		//计算key对应的数字
		size_t hash1 = HashFunc1()(key) % N;
		size_t hash2 = HashFunc2()(key) % N;
		size_t hash3 = HashFunc3()(key) % N;
		//将key在位图上对应的位置找到进行置1
		_bs.set(hash1);
		_bs.set(hash2);
		_bs.set(hash3);

		//cout << hash1 << " " << hash2 << " " << hash3 << " " << endl;
	}

	bool Test(const K& key)
	{
		size_t hash1 = HashFunc1()(key) % N;
		//检查当前key不在,一定正确
		if (_bs.test(hash1) == false)
			return false;
		size_t hash2 = HashFunc2()(key) % N;
		if (_bs.test(hash2) == false)
			return false; 
		size_t hash3 = HashFunc3()(key) % N;
		if (_bs.test(hash3) == false)
			return false;
		//说明三个值都在,不一定正确,可能有误判情况
		return true;
	}
private:
	bitset<N> _bs;
};

三种哈希函数
由于要用三种不同的哈希算法进行计算来降低冲突,因此,可以选择3种不同的哈希算法:

BKDR

struct HashBKDR
{
	size_t operator()(const string& s)
	{
		size_t value = 0;
		for (auto e : s)
		{
			value += e;
			value *= 131;
		}
 
		return value;
	}
};

AP

struct HashAP
{
	size_t operator()(const string& s)
	{
		register size_t hash = 0;
		size_t ch;
		for (long i = 0; i < s.size(); i++)
		{
			ch = s[i];
			if ((i & 1) == 0)
			{
				hash ^= ((hash << 7) ^ ch ^ (hash >> 3));
			}
			else
			{
				hash ^= (~(hash << 11) ^ ch ^ (hash >> 5));
			}
		}
 
		return hash;
	}
};

DJB

struct HashDJB
{
	size_t operator()(const string& s)
	{
		register size_t hash = 5381;
		for (auto e : s)
		{
			hash += (hash << 5) + e;
		}
 
		return hash;
	}
};

删除
布隆过滤器不能直接支持删除工作,因为在删除一个元素时,可能会影响其他元素

比如:删除"钟楼"元素,如果直接将该元素所对应的二进制比特位置0,“华山”元素也被删除了,因为这两个元素在多个哈希函数计算出的比特位上刚好有重叠。

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

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

相关文章

外汇天眼:什么是外汇隔夜利息、滑点和价格跳空?

隔夜利息 所有的外汇交易中只要持仓过夜就一定会有隔夜利息&#xff0c;只不过这个利息有可能是正的&#xff0c;也有可能是负数。 买一个货币涨&#xff0c;相当于我们卖出对应货币&#xff0c;买入基础货币。 买一个货币跌&#xff0c;相当于我们向外汇平台卖出基础货币&a…

定制耐酸碱移液吸头PFA移液枪头可重复使用

移液枪是移液器的一种&#xff0c;常用于实验室少量或微量液体的移取&#xff0c;规格不同&#xff0c;不同规格的移液枪配套使用不同大小的枪头&#xff0c;不同生产厂家生产的形状也略有不同&#xff0c;但工作原理及操作方法基本一致。移液枪属精密仪器&#xff0c;使用及存…

开启鸿蒙开发探索之旅ArkTS基本语法介绍(3)

上一章简单的介绍了鸿蒙HUAWEI DevEco Studio框架的搭建&#xff0c;这一章讲一下鸿蒙的主要开发一眼ArkTS的基本语法结构 1.ArkTS语法解释 ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript&#xff08;简称TS&#xff09;生态基础上做了进一步扩展&…

Redis的主从配置,哨兵模式,集群模式

目录 什么是主从复制&#xff1f; 主从复制的作用&#xff1f; 主从复制的流程&#xff1f; 搭建Redis的主从复制 安装Redis 环境准备 修改内核参数 安装Redis 定义systemd服务管理脚本 修改Redis配置文件&#xff08;Master节点操作&#xff09;192.168.17.25 修改Re…

计算机网络技术-2022期末考试解析

【前言】 这是计算机网络技术这门课&#xff0c;感觉和计网还是有不一样的&#xff0c;但也有能做的&#xff0c;把能做的做了。 一、单项选择题&#xff08;每题2分&#xff0c;共20分&#xff09; 1. 用于测试两台计算机连通状况的命令是 。 ( ) A. cmd B. ping C. ipconf…

(N-137)基于springboot,vue运动会报名管理系统

开发工具&#xff1a;IDEA 服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8 项目构建&#xff1a;maven 数据库&#xff1a;mysql5.7 系统分前后台&#xff0c;项目采用前后端分离 前端技术&#xff1a;vueAvueElementUI 服务端技术&#xff1a;springbootmybatis 本项…

如何利用ChatGPT快速生成月报?

随着每个月的结束&#xff0c;个人和团队经常需要编写月报来回顾和总结。这项任务通常消耗大量时间和精力。幸运的是&#xff0c;借助ChatGPT&#xff0c;这个过程可以变得更加简单和高效。接下来&#xff0c;我将详细介绍如何利用ChatGPT快速生成月报&#xff0c;从而帮助你节…

简易实现 MyBatis 底层机制

MyBatis 大家好呀&#xff01;我是小笙&#xff0c;我中间有1年没有更新文章了&#xff0c;主要忙于毕业和就业相关事情&#xff0c;接下来&#xff0c;我会恢复更新&#xff01;我们一起努力吧&#xff01; 概述 MyBatis 是一个持久层的框架&#xff08;前身是 ibatis&#x…

jmeter--常用插件及服务器监控(14)

一.jmeter插件管理器 下载jmeter插件管理器&#xff1a;plugins-manager.jar 下载plugins-manager.jar并将其放入lib/ext目录&#xff0c;然后重启JMeter。 插件管理界面 打开选项->Plugins Manager&#xff08;界面见下图&#xff09;&#xff0c;“Installed Plugns”…

Github全球第一的免费waf防火墙雷池社区版的语义分析检测算法

传统规则防护&#xff0c;在当下为什么失灵&#xff1f; 当下&#xff0c;Web 应用防火墙大多采用规则匹配方式来识别和阻断攻击流量&#xff0c;但由于 Web 攻击成本低、方式复杂多样、高危漏洞不定期爆发等原因&#xff0c;管理者们在安全运维工作中不得不持续调整防护规则&a…

回顾2023,立2024flag

文章目录 回顾2023与CSDN相识专栏整理数据回顾 立2024flag 回顾2023 在过去的一年里&#xff0c;前端技术不断演进和创新。新技术、新框架层出不穷&#xff0c;给前端工程师提供了更多选择和挑战。2023年已经成为过去&#xff0c;回首这一年&#xff0c;我们也经历了许多挑战和…

@RequestParam

在我们写接口的时候&#xff0c;经常会用到这个注解来标记参数&#xff0c;通过这个注解我们可以把请求的url中的参数名和值映射到被标记的参数上。 比如下方&#xff0c;这个接口是通过传入的参数来查询相关信息的 我们定义这样一个接口&#xff0c;设置了8个参数&#xff0c;…

ChatGPT本地部署,学习记录

一、GPT4ALL模型 官网地址&#xff1a; Github&#xff1a;https://github.com/nomic-ai/gpt4all GPT4ALL项目部署简易&#xff0c;但是在运行体验上一般&#xff0c;并且是只调用CPU来进行运算。 看官方文档介绍在嵌入式上有比较大的优势&#xff0c;但是目前个人对嵌入式…

云贝教育 |【技术文章】存储对象的LIBRARY CACHE LOCK/PIN实验(一)

注: 本文为云贝教育 刘峰 原创&#xff0c;请尊重知识产权&#xff0c;转发请注明出处&#xff0c;不接受任何抄袭、演绎和未经注明出处的转载。 实验环境 操作系统&#xff1a;Red Hat Enterprise Linux release 8.8 (Ootpa) 数据库&#xff1a;oracle Version 19.3.0.0.0 …

Nginx介绍与安装

目录 nginx服务 1、Nginx 介绍 2、为什么选择 nginx 3、IO多路复用 1、I/O multiplexing【多并发】 2、一个请求到来了&#xff0c;nginx使用epoll接收请求的过程是怎样的? 3、异步&#xff0c;非阻塞 4、nginx 的内部技术架构 5、yum安装部署nginx和配置管理 1.获取…

Vue学习笔记六--Vue3学习

1、Vue3的优势 2、创建Vue3工程 前提&#xff1a;node -v 查看node版本&#xff0c;需要在16.0及以上 创建命令 npm init vuelatest,先安装create-vue然后创建项目 然后执行npm run dev 提示 sh: vite: command not found,需要执行npm i重新安装依赖&#xff0c;之后再执行np…

13.若依代码自动生成功能详解

文章目录 1.代码自动生成功能2.功能的使用3. 代码的导出和使用 1.代码自动生成功能 基于若依的目录结构&#xff0c;若依本身提供了代码生成功能&#xff0c;可以根据数据库表的内容&#xff0c;生成一些基本的CRUD的前后端的功能。本文将生成过程中的一些注意事项&#xff0c…

Windows系统设置会议闹钟铃声提醒怎么操作的

在这个快节奏的时代&#xff0c;我们每个人都像是被时间推着走。过去&#xff0c;我经常会因为埋头于工作而忘记了即将召开的会议&#xff0c;直到同事打来电话催促&#xff0c;才匆匆忙忙地赶去会议室。这种尴尬的经历让我意识到&#xff0c;我需要一个能够准时提醒我参加会议…

UI功能6大流程、接口测试8大流程这些你真的全会了吗?

在讲接口流程测试之前&#xff0c;首先需要给大家申明下&#xff1a;接口测试对于测试人员而言&#xff0c;非常非常重要&#xff0c;懂功能测试接口测试&#xff0c;就能在企业中拿到一份非常不错的薪资。 这么重要的接口测试&#xff0c;一般也是面试笔试必问。为方便大家更…

屡创佳绩!玻色量子与平安银行持续深化“量子计算+金融”创新合作

2024年1月4日&#xff0c;玻色量子凭借与平安银行联合发布的“信贷风险数据降维”量子计算真机测试优秀案例&#xff0c;成功荣登“2023年度产业数字化转型案例”之“新锐科技企业”榜单。这是双方在“量子金融”领域取得的又一重要研究成果。 2024年开年&#xff0c;玻色量子已…