位图的实现与应用

目录

位图

实现思路

模拟实现

类模板

构造函数

set

reset

test

twobitset 实现

成员变量

set

is_once

布隆过滤器

成员变量与模板

set

test

删除


位图

位图是哈希的另一种表现,与我们常用的 set map 的思想还是基本一样的,下面我们看一下简单位图的实现:

实现思路

  • 在位图的实现中,我们想要用一个比特位,来表示一个数据的状态信息(也就是是否存在)。

  • 所以一个位图并不能表示一个数据存储/出现过的次数。

  • 但是在 C/C++ 的内置类型中并未有单位是比特位的类型,所以这个还是需要我们开空间的时候自己计算。

  • 其中开空间我们可以使用我们已知的数据类型去开空间例如:char、int。

  • 虽然上面只说了两种数据类型,但是并不是只有这两种可以使用,只是这两种比较常见,且容易控制。

  • 如果是 int 的话,那么开一个 int 空间就是开了 32 个比特位,也就是一个 int 可以存储 32 个数据的状态。

模拟实现

  • 当我们使用位图的时候,由于只有用户知道自己想要存储的数据的范围,所以位图的空间需要有用户来决定

  • 所以位图需要一个非类型模板参数用来表示可以存储的数据范围

类模板

    template<size_t N>class bitset{public:private:vector<int> _a;};
  • 这里我们使用 int 类型来控制。

  • 这里的非类型模板参数传过来的值,就可以在构造函数里面为 _a 开一段所需要的空间。

构造函数

        bitset(){_a.resize(N / 32 + 1);}
  • 由于这里使用的是 int 所以我们开辟的空间需要 N / 32,但是 N / 32 是向下取整,所以如果这样的话,我们还需要对除后的值多开一个 int 类型,防止开的空间不够。

set

  • set 就是将一个值设置到位图中

  • 设置进位图就是将对应的比特位设置为 1

  • 我们只需要让该比特位或 1 ,其他位为 0 即可

  • 我们可以将 1 像左移动到该比特位,然后与该值或等,由于或是有1为1,所以我们可以将该比特位设置为1

  • 在设置之前,我们还需要计算出对应的比特位的位置吗,由于我们使用的是 int 所以我们想知道到第几个比特位,我们就可以对该值进行除32 就是在对应的数组位置,然后我们知道了对应的数组位置,我们还需要知道该比特位在该数组位置的第几个比特位,所以我们还可以用该值对 32 进行取模操作,我们就知道对应的比特位了

  • 下面看代码会很容易理解

        void set(int n){int i = n / 32;int j = n % 32;
​_a[i] |= 1 << j;}

reset

  • reset 就是将一个比特位移除,也就是将该比特位设置为 0

  • 想要将一个比特位设置为 0 ,我们可以对该比特位与等一个0,其他位为1即可

  • 还是看代码容易理解,或者可以自己写一下

        void reset(int n){int i = n / 32;int j = n % 32;
​_a[i] &= ~(1 << j);}

test

  • test 就是用来探测一个值是否在位图中,如果为1 则在位图中,如果为 0 ,则不在位图中

  • 其实我们想知道一个比特位在位图中是否为1或者是0,我们可以对该比特位与1,如果结果是1,则说明该比特位表示的值是存在的,如果为0,表示该比特位表示的值并不存在

        bool test(int n){int i = n / 32;int j = n % 32;
​return _a[i] & 1 << j;}

如果我们这里有一堆数字,我们想要判断这些数字中只出现了一次的值是什么,那么我们怎么使用位图来解决?

思路:由于一个位图只能表示在不在,那么我们可不可以有两个比特位,入如果有两个比特位,比那么我们就可以表示很多情况了 例如: 0 0 0 1 1 0 1 1,有上面四种情况,但是我们只需要判断出现了一次的数字,那么我们其实用不了四种情况,我们只需要三个就可以了, 0 0 表示没有出现过, 0 1 表示出现了一次, 1 0 表示出现了两次或者是两次以上,所以我们可以使用两个位图来表示:

twobitset 实现

成员变量

  • 上面说了,我们需要用两个位图来表示,所以我们需要两个位图

template<size_t N>class twobitset{public:private:bitset<N> _b1;bitset<N> _b2;};

set

  • 这里的 set 就需要分情况了,如果一次都没有出现,那么就是让 _b1 变为 0, _b2 变为 1,也就是 0 1

  • 如果这里已经出现了一次了,那么就是让 0 1 变为 1 0 所以我们需要让_b1 变为 1, _b2 变为 0 也即是 1 0

        void set(int n){// 0  0 -> 0  1if (!_b1.test(n) && !_b2.test(n)){_b2.set(n);} // 0  1 -> 1  0else if (!_b1.test(n) && _b2.test(n)){_b1.set(n);_b2.reset(n);}}

is_once

  • 既然我们需要知道师傅出现了一次,那么我们当然需要有一个函数用来判断是否出现了一次

  • 如果 _b1 是 0 _b2 是 1 那么就表明出现了一次,否则就不是一次

        bool is_once(int n){return !_b1.test(n) && _b2.test(n);}

布隆过滤器

  • 位图只能用来表示整数是否存在,那么如果还想表示其他类型,例如:字符串?

  • 布隆过滤器就可以用来解决这个问题

  • 这里可以使用 hash 函数对字符串进行映射,然后将映射出来的值作为整数放到位图里面

  • 但是,我们知道hash函数是会出现冲突的,如果字符串很多的话,那么冲突是很多的

  • 其中,我们可以将一个字符串使用多个hahs函数映射出来不同的值,然后将hahs函数映射出来的值都放到位图里面,这样有几个hahs函数就可以映射几个比特位,这样就可以减少冲突

  • 怎么探测是否存在呢?既然一个字符串映射了好几个hash比特位,所以我们探测是否存在的时候,也需要探测这些对应的比特位是否存在,只要有一个比特位不存在,则说明该字符串不存在

  • 但是即使是通过了多次的映射,也还会产生冲突,剩下的介绍冲突的做法就是增加空间了

成员变量与模板

  • 我们可以将hash函数作为模板传过去,可以使用仿函数来调用这些函数

  • 我们的成员变量就是一个位图

template<size_t N, class K = string, class Hash1 = BKDRHash, class Hash2 = APHash, class Hash3 = DJBHash>class bloomfilter{public:private:bitset<N> _bs;};

我们可以看一下这些hash函数

struct BKDRHash
{size_t operator()(const string& str){size_t hash = 0;for (char ch : str){hash = hash * 131 + ch;}return hash;}
};
 
struct APHash
{size_t operator()(const string& str){size_t hash = 0;size_t ch;for (long i = 0; i < str.size(); i++){if ((i & 1) == 0){hash ^= ((hash << 7) ^ str[i] ^ (hash >> 3));}else{hash ^= (~((hash << 11) ^ str[i] ^ (hash >> 5)));}}return hash;}
};
struct DJBHash
{size_t operator()(const string& str){if (str.size() == 0)return 0;size_t hash = 5381;for (char ch : str){hash += (hash << 5) + ch;}return hash;}
};

set

  • set 函数就是有几个 hash 函数,我们就映射几个位置,但是也不是hash函数越多越好,只是在特定的范围内,hash函数多了可以减少冲突

  • 上面我们使用了3个hash函数

  • 上面的hash函数可以参考该网站:

    [各种字符串 hash 函数]  https://www.cnblogs.com/-clq/archive/2012/05/31/2528153.html 

           void set(const K& key){size_t hash1 = Hash1()(key) % N;_bs.set(hash1);size_t hash2 = Hash2()(key) % N;_bs.set(hash2);size_t hash3 = Hash3()(key) % N;_bs.set(hash3);cout << hash1 << " " << hash2 << " " << hash3 << endl;}

test

  • 在布隆过滤器中,一个字符串映射了多个位置,所以如果想要探测该字符串是否存在,那么就需要探测这些是否位置是否被映射,只要有一个为假,那么该字符串便不存在

  • 我们前面说过,布隆过滤器是有冲突的,所以又可能有一个不存在的字符串被识别为存在,所以说,判断是否存在不是很准确的

  • 但是不存在是存在是准确的

        bool test(const K& key){size_t hash1 = Hash1()(key) % N;size_t hash2 = Hash2()(key) % N;size_t hash3 = Hash3()(key) % N;return _bs.test(hash1) && _bs.test(hash2) && _bs.test(hash3);}

删除

  • 如果我们想要删除布隆过滤器中的一个值,那么我们怎么删除?

  • 其实布隆过滤器中的值是不能删除的,为什么?我们前面为了减少冲突,我们是一个值映射了多个位置。

  • 所以我们的一个比特位可能被多个值映射过,如果我们直接删除了的话,我们就可能导致其他值也找不到,所以不能删除。

  • 那么如果想要实现删除呢?

  • 我们可以多搞一些比特位,其中两个比特位可以表示到 3,所以如果我们想要删除,我们至少要 8 个比特位,而且 8 个比特位也不一定就足够了,如果我们搞这么多比特位,那么范围违背了我们的原则,我们使用布隆过滤器就是为了占用少量的空间,此时反而使用了很多空间,那么显然是不划算的。

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

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

相关文章

leetcode面试题0808有重复字符串的排列组合

描述 输入一个长度为 n 字符串&#xff0c;打印出该字符串中字符的所有排列&#xff0c;你可以以任意顺序返回这个字符串数组。 例如输入字符串ABC,则输出由字符A,B,C所能排列出来的所有字符串ABC,ACB,BAC,BCA,CBA和CAB。 数据范围&#xff1a;n<10 要求&#xff1a;空间复…

引领初创企业的数字化转型:选择适合的低代码平台

初创企业在初期各项架构都还不完善&#xff0c;对于应用程序的需求多样&#xff0c;但是又要考量成本。所以&#xff0c;低代码平台就是在综合考量成本和需求的情况下的一个突出的选择。下面我们就六个方面为您介绍&#xff1a;初创企业选择的Zoho Creator低代码平台。 1、功能…

机器学习笔记 - k-NN算法的数学表达

一、概述 所有的机器学习算法都是有假设前提的。k-NN算法的假设前提是相似的输入有相似的输出。其分类规则是对于测试输入x,在其k个最相似的训练输入中分配最常见的标签。 k-NN 的正式定义: 对于一个待测试数据。 将的个最近邻的集合表示为 。的正式定义为 ,并且。(意思就是…

mmdetection v3避坑

命令&#xff1a; python tools/test.py projects/DiffusionDet/configs/diffusiondet_r50_fpn_500-proposals_1-step_crop-ms-480-800-450k_coco.py /data/zhangrui/mmdetection-master/checkpoints/diffusiondet_r50_fpn_500-proposals_1-step_crop-ms-480-800-450k_coco_202…

云计算的发展趋势和挑战

本文将探讨云计算的发展趋势和挑战&#xff0c;旨在帮助读者了解云计算的最新动态和未来发展方向。 随着信息技术的发展&#xff0c;云计算作为一种新兴的计算模式&#xff0c;已经得到了广泛的应用和认可。它通过将计算资源、存储资源和应用程序等服务通过互联网提供给用户&a…

华为OD机试真题- 阿里巴巴找黄金宝箱(IV)-2023年OD统一考试(B卷)

题目描述: 一贫如洗的樵夫阿里巴巴在去砍柴的路上,无意中发现了强盗集团的藏宝地,藏宝地有编号从0~N的箱子,每个箱子上面贴有一个数字,箱子排列成一个环,编号最大的箱子的下一个是编号为0的箱子。 请输出每个箱子贴的数字之后的第一个比它大的数,如果不存在则输出-1。 …

Linux第一次作业

一&#xff0c;作业问题&#xff1a; 二&#xff0c;问题解答&#xff1a; 1. 2.文件管理命令练习 3.vi/vim练习 3.1 3.2 3.3 3.4

产品文档-BRD、MRD和PRD

1、BRD&#xff08;Business Requirement Document&#xff09;&#xff0c;商业需求文档&#xff0c;是一份产品商业论证报告&#xff0c;基于商业目标或价值所描述的产品需求内容文档&#xff0c;是领导层进行产品研发立项决策评估的重要依据&#xff0c;是产品生命周期中最早…

消除达人游戏小程序开发流程:专业性与创新的结合

在移动互联网时代&#xff0c;达人游戏小程序逐渐成为了用户追逐娱乐的一种方式。为了满足用户对于达人游戏的需求&#xff0c;开发一款专业且具有创新性的达人游戏小程序显得尤为重要。本文将从需求分析、技术选型、系统设计和用户体验等多个方面&#xff0c;深入探讨达人游戏…

题目 1062: 二级C语言-公约公倍

输入两个正整数m和n&#xff0c;求其最大公约数和最小公倍数。样例输入 2 3样例输出 1 6 这题一知半解的&#xff0c; 最小公倍数两数の积/最大公约数&#xff1b; 最大公约数通过迭代法求得(见其下)&#xff0c; 作为a,b两数有一个属为有一个为0为无效数据时 《-----a%b等…

2023.9.23-最强实战:Typora+mkdocs构建自己的知识库博客

最强实战&#xff1a;Typoramkdocs构建自己的知识库&博客-2023.9.23 winodws-ecs-rsync-mkdocs-typora-百度网盘同步空间数据维护方案 目录 实验环境 win10 typora v1.7.4 mkdocs, version 1.5.2 vscode v1.82.2 阿里云轻量服务器实验软件 链接&#xff1a;https://pan.…

sh文件介绍及linux下执行

Shell脚本是一种用于自动化任务和系统管理的脚本语言。它允许用户通过命令行界面执行一系列命令&#xff0c;从而简化了重复性任务的处理过程。 以下是关于Shell脚本的一些基本概念&#xff1a; 1. Shell脚本通常以“.sh”扩展名保存&#xff0c;例如“script.sh”。 2. Shell…

算法 旋转数组最小数字-(二分查找+反向双指针)

牛客网: BM21 题目: 非降数组旋转后的最小值 思路: 数组形状呈现从小到大&#xff0c;再从小到大&#xff0c;左半段的值均大于右半段的值&#xff0c;需找到中间的最小值。初始化双指针left 0, right n-1, mid left (right-left)/2, 如果nums[mid] < nums[right],说明…

单片机论文参考:3、基于单片机的电子万年历设计

摘要 随着社会、科技的发展&#xff0c;人类得知时间&#xff0c;从观太阳、摆钟到现在电子钟&#xff0c;不断研究、创新。为了在观测时间&#xff0c;能够了解与人类密切相关的信息&#xff0c;比如星期、日期等&#xff0c;电子时钟诞生了&#xff0c;它集时间、日期、星期等…

005:vue2使用vue-type-writer实现打字机效果

Vue Type Writer是一个Vue.js 2打字机效果组件&#xff0c;支持像打字机一样模仿键入文本。 文章目录 1. 效果2. 安装使用 1. 效果 2. 安装使用 npm 安装 npm install vue-type-writer --save完整代码 <template><div class"app-container home"><…

2023.9.11 关于传输层协议 UDP和TCP 详解

目录 UDP协议 TCP协议 TCP十大核心机制 确认应答 超时重传 连接管理&#xff08;三次握手 四次挥手&#xff09; 滑动窗口 流量控制 拥塞控制 延时应答 捎带应答 面向字节流 粘包问题 TCP 中的异常处理 经典面试题 对比 TCP 和 UDP 如何使用 UDP 实现可靠传…

Spring面试题15:Spring支持几种bean的作用域?singleton、prototype、request的区别是什么?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:Spring支持几种bean的作用域? Spring支持以下几种Bean的作用域: Singleton(单例):这是Spring默认的作用域。使用@Scope(“singleton”)注解或…

【观察】数字化转型的“下半场”,华为加速行业智能化升级

过去几年数字化转型席卷全球&#xff0c;随着新技术的广泛应用&#xff0c;新的机会和价值正在不断被发现和创造。从某种程度上说&#xff0c;数字化转型不再是“可选项”&#xff0c;而变成了“必选项”。 目前&#xff0c;已经有超过170多个国家和地区制定了各自的数字化相关…

Spring面试题17:Spring中什么是bean装配?有哪几种自动装配方式?自动装配有哪些局限性?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:Spring中什么是bean装配? 在Spring中,Bean装配是指将一个或多个Bean实例化、配置和组合在一起的过程。它是Spring容器的核心功能之一,通过Bean装…