STL容器之哈希的补充——其他哈希问题

1.其他哈希问题

​ 减少了空间的消耗;

1.1位图

​ 位图判断在不在的时间复杂度是O(1),速度特别快;

​ 使用哈希函数直接定址法,1对1映射;

​ 对于海量的数据判断在不在的问题,使用之前的一些结构已经无法满足,空间消耗过于严重,位图则可以较好的解决此问题;

​ 对于bit位的改变除了位运算就是位段;

1.1.2位图结构的实现

​ 小端机与我们看数据的顺序相反,几个数据连续存储从低地址到高地址,低位-高位,低位-高位。

namespace Bitset
{template <size_t N>//无符号整数42亿9千万,需要每个整数用一个bit位来标识在不在,大约500兆class BitSet{public:// 用构造函数开空间BitSet(){a_.resize(N / 32 + 1);}public:// 将x映射的哪个标记映射成为1void set(size_t x){size_t i = x / 32;size_t j = x % 32;a_[i] |= (1 << j); // 小端机,开头就是低位,所以直接左移j位}// 将x映射的哪个标记映射成为0void reset(size_t x){size_t i = x / 32;size_t j = x % 32;a_[i] &= (~(1 << j));}bool test(size_t x){size_t i = x / 32;size_t j = x % 32;return a_[i] & (1 << j);// if (a_[i] & (1 << j))// {//     std::cout << "存在" << std::endl;//     return true;// }// else// {//     std::cout << "不存在" << std::endl;//     return false;// }}private:std::vector<int> a_;};
}
1.1.3库里面对于位图结构的实现

在这里插入图片描述

1.1.4位图的扩展

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

​ 思路1:使用两个比特位组合,来表示没有出现,出现一次和出现两次及以上;

​ 思路2:使用2个位图,对应位置组合使用;

2.两个文件分别有100亿整数,1g内存找交集;

1.1.5位图的应用

1.快速查找某个数据是否在一个集合中

2.排序 + 去重

3.两个集合的交集、并集等

4.操作系统中磁盘块标记

1.2布隆过滤器

​ 作用:过滤掉确定性的数据,降低数据库的查询负载压力;对于不确定的数据,降低误判率;

​ 使用除留余数法,产生多对一,对于整型可以使用位图来实现,对于字符串是先对应一个整数,但是不可能无限扩容,会存在双重哈希冲突,对于存在可能误判,是不准确的,而对于不存在一定是准确的;

布隆过滤器是由布隆(Burton Howard Bloom)在1970年提出的 一种紧凑型的、比较巧妙的概率型数据结构,特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”,它是用多个哈希函数,将一个数据映射到位图结构中。此种方式不仅可以提升查询效率,也可以节省大量的内存空间。

​ 使用布隆过滤器可以减少误判率;一个值映射位图的多个位置,如果多个位置都为1,才能说明在;就像是现实生活中,信息越多描述就更准确;

1.2.1应用场景

​ 1.不需要精确的场景,即使用降低误判的特性:比如快速判断昵称是否被使用过,将昵称存放到一个布隆过滤器里面,存在误判,但是可以接受,比如用户知道昵称不可用就会自动用其他昵称,不会产生巨大的问题;

​ 2.需要精确的场景,即使用不存在是准确的特性,昵称不存在快速响应,昵称存在去数据库进行查找,可以起到过滤一部分确定数据的效果;

​ 3.布隆过滤器不仅可以过滤字符串,也可以针对其他类型;

1.2.2布隆过滤器模拟实现

​ 偶数用位运算表示,n&1==0,就是偶数;

​ 使用不同的哈希算法得到不同的整数映射,多对一的映射减少了误判,同时也带来了空间上的消耗空间减少也会增加误判的机率;

一般不允许使用reset,否则会影响很多映射,即多对一使得关联度增加了,一个修改就会影响另一个,可以使用引用计数的方法,同时还需要多开空间存计数,这样就可以保护数据。

namespace Bloomfilter
{struct BKDR{size_t operator()(const std::string &str){size_t i = 0;for (const auto &e : str){i *= 131;i += e;}return i;}};struct AP{size_t operator()(const std::string &str){size_t hash = 0;for (size_t i = 0; i < str.size(); i++){size_t ch = str[i];if ((i & 1) == 0)hash ^= ((hash << 7) ^ ch ^ (hash >> 3));elsehash ^= (~((hash << 11) ^ ch ^ (hash >> 5)));}return hash;}};struct DJB{size_t operator()(const std::string &str){size_t hash = 5381;for (auto ch : str){hash += (hash << 5) + ch;}return hash;}};template <size_t N, class K = std::string, class Hash1 = BKDR, class Hash2 = AP, class Hash3 = DJB> // 可以使用BKDR算法class BloomFilter{public:void set(const K &key){size_t hash1 = BKDR()(key) % N;bf_.set(hash1);size_t hash2 = AP()(key) % N;bf_.set(hash2);size_t hash3 = DJB()(key) % N;bf_.set(hash3);}bool test(const K &key){size_t hash1 = BKDR()(key) % N;if (bf_.test(hash1) == false){return false;}size_t hash2 = AP()(key) % N;if (bf_.test(hash2) == false){return false;}size_t hash3 = DJB()(key) % N;if (bf_.test(hash3) == false){return false;}return true; // 存在误判}private:// 私有成员std::bitset<N> bf_;};
}
1.2.3哈希函数个数和布隆过滤器长度的选择

在这里插入图片描述

k为哈希函数的个数,m为布隆过滤器的长度,n为插入元素的个数,这样可以使得误判率相对较低;

1.2.4布隆过滤器优缺点

优点:

1.增加和查询元素的时间复杂度为:O(K), (K为哈希函数的个数,一般比较小),与数据量大小无关 ;

2.哈希函数相互之间没有关系,方便硬件并行运算 ;

3.布隆过滤器不需要存储元素本身,在某些对保密要求比较严格的场合有很大优势;

4.在能够承受一定的误判时,布隆过滤器比其他数据结构有着很大的空间优势 ;

5.数据量很大时,布隆过滤器可以表示全集,其他数据结构不能 ;

6.使用同一组散列函数的布隆过滤器可以进行交、并、差运算 ;

缺点:

1.有误判率,即存在假阳性(False Position),即不能准确判断元素是否在集合中(补救方法:再建立一个白名单,存储可能会误判的数据) ;

2.不能获取元素本身 ;

3.一般情况下不能从布隆过滤器中删除元素 ;

4.如果采用计数方式删除,可能会存在计数回绕问题 ;

8.2.5布隆过滤器的扩展

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

精确算法和近似算法 ;

2.如何扩展BloomFilter使得它支持删除元素的操作 ;

1.3哈希切割

​ 问题:1.将大文件切割是因为在磁盘中查找太慢,应载入内存查找;2.平均切分要查询的key在每个小文件中都可能存在,都得查找一次;

​ 而是用哈希切割,将大文件进行切割,切割成N份,用哈希算法将查询字符串映射成整数,然后%N,最后得到的映射值i就是被切割的第i个小文件;这样就可以根据编号进行查找,不用遍历所有的小文件;

​ 原理是:存在哈希冲突映射了错误的值,但是正确的值一定在这个位置对应的小文件,使得范围大幅度减少;即过滤很大一批无效数据;

1.3.1哈希切割应用

​ 1.哈希切割解决大文件找交集;

​ 哈希切分后还可能某一个小文件过大;文件过大可能是1.大多数query冲突;2.大多数query相同,部分冲突;

​ 对于小文件过大的解决方法:1.set去重,如果成功说明有大量相同数据,这样文件就小了,如果失败抛异常,则对此文件,使用其他哈希函数进行二次哈希切分,这样文件也小了;

​ 2.最大/topk问题

​ 哈希切割完,用map统计次数,然后用另一个值记录最大的值,清理map遍历其他小文件,更新最大值;

如果是topk就建立一个k个值的小堆,插入k个较大值然后不断更新;

补充:CPU的高速缓存与内存和磁盘间的局部性原理的预加载机制

​ CPU高速缓存是,内存会将一段数据先加载到cache中,CPU会向cache进行读取,存在缓存命中问题;

​ 局部性原理的预加载机制是,内存磁盘读取都是按照一定的大小进行的,这样就可以一次性读到多个数据;

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

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

相关文章

基于PSO粒子群算法的三角形采集堆轨道优化matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 假设一个收集轨道&#xff0c;上面有5个采集堆&#xff0c;这5个采集堆分别被看作一个4*20的矩阵&#xff08;下面只有4*10&#xff09;&#xff0c;每个模块&…

opencv编程

opencv编程 引言&#xff1a; ​ 本实验旨在介绍使用OpenCV进行图像处理和视频处理的基本操作。OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源计算机视觉库&#xff0c;提供了丰富的图像和视频处理功能&#xff0c;既可以进行图像的读取、显示…

187基于matlab的弹道目标跟踪滤波方法

基于matlab的弹道目标跟踪滤波方法&#xff0c;扩展卡尔曼滤波&#xff08;extended Kalman filter, EKF&#xff09;、转换测量卡尔曼滤波&#xff08;conversion measurement Kalman filter, CMKF&#xff09;跟踪滤波&#xff0c;得到距离、方位角、俯仰角误差结果。程序已调…

人工智能|机器学习——DBSCAN聚类算法(密度聚类)

1.算法简介 DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种基于密度的聚类算法&#xff0c;簇集的划定完全由样本的聚集程度决定。聚集程度不足以构成簇落的那些样本视为噪声点&#xff0c;因此DBSCAN聚类的方式也可以用于异常点的检测。 2.算法原…

《汇编语言》- 读书笔记 - 第17章-实验17 编写包含多个功能子程序的中断例程

《汇编语言》- 读书笔记 - 第17章-实验17 编写包含多个功能子程序的中断例程 逻辑扇区根据逻辑扇区号算出物理编号中断例程&#xff1a;通过逻辑扇区号对软盘进行读写 代码安装 int 7ch 测试程序效果 实现通过逻辑扇区号对软盘进行读写 逻辑扇区 计算公式: 逻辑扇区号 (面号*8…

CSS基础知识

font-family: "Trebuchet MS", Verdana, sans-serif; 字体栈&#xff0c;浏览器会一个一个试过去看下哪个可以用 font-size16px; font-size1em; font-size100%;//相对于16px 字体大小&#xff0c;需要进行单位换算16px1em font-weightnormal;//400font-weight属性…

YoloV5改进策略:Block改进|自研Block,涨点超猛|代码详解|附结构图

涨点效果 参考模型 参考的Block,如下图: 我对Block做了修改,修改后的结构图如下: 代码详解 from timm.models.layers import DropPathfrom torch import Tensor def channel_shuffle(x: Tensor, groups:

用Java Socket手撸了一个HTTP服务器

作为一个 Java 后端&#xff0c;提供 HTTP 服务可以说是基本技能之一了&#xff0c;但是你真的了解 HTTP 协议么&#xff1f;你知道知道如何手撸一个 HTTP 服务器么&#xff1f;Tomcat 的底层是怎么支持 HTTP 服务的呢&#xff1f;大名鼎鼎的 Servlet 又是什么东西呢&#xff0…

可观测性是什么?新手入门指南!

如果您之前对可观测性重要性&#xff0c;益处&#xff0c;以及组成不甚了解&#xff0c;本文是一个合适的指南手册。 什么是可观测性&#xff1f; 可观测性被定义为根据系统产生的输出数据&#xff08;如日志&#xff0c;指标和链路追踪&#xff09;来衡量当前系统运行状态的…

代码理解 pseudo_labeled = outputs.max(1)[1]

import torchls torch.Tensor([[0.2,0.4],[0.3,0.2]]) print(ls.max(1))

STL之deque容器代码详解

1 基础概念 功能&#xff1a; 双端数组&#xff0c;可以对头端进行插入删除操作。 deque与vector区别&#xff1a; vector对于头部的插入删除效率低&#xff0c;数据量越大&#xff0c;效率越低。 deque相对而言&#xff0c;对头部的插入删除速度回比vector快。 vector访问…

Unity Shader实现UI流光效果

效果&#xff1a; shader Shader "UI/Unlit/Flowlight" {Properties{[PerRendererData] _MainTex("Sprite Texture", 2D) "white" {}_Color("Tint", Color) (1, 1, 1, 1)[MaterialToggle] PixelSnap("Pixel snap", float…

简洁的在线观影开源项目

公众号&#xff1a;【可乐前端】&#xff0c;每天3分钟学习一个优秀的开源项目&#xff0c;分享web面试与实战知识。 每天3分钟开源 hi&#xff0c;这里是每天3分钟开源&#xff0c;很高兴又跟大家见面了&#xff0c;今天介绍的开源项目简介如下&#xff1a; 仓库名&#xff1…

海外媒体发稿:7种媒体套餐推广策略解析-华煤舍

有效的媒体宣传策略对于产品或服务的推广至关重要。本文将介绍7种媒体套餐推广策略&#xff0c;帮助您惊艳市场&#xff0c;并取得成功。以下是每种策略的拆解描述&#xff1a; 1. 广告投放 广告投放是最常见的宣传手段之一。通过在各种媒体平台上购买广告&#xff0c;如电视、…

Web渗透测试流程

什么是渗透测试 渗透测试 (penetration test),是通过模拟恶意黑客的攻击方法&#xff0c;来评估计算机网络系统安全的一种评估方法。这个过程包括对系统的任何弱点、技术缺陷或漏洞的主动分析&#xff0c;这个分析是从一个攻击者可能存在的位置来进行的&#xff0c;并且从这个…

linux 查看打开使用了哪些端口

你可以使用 netstat 命令来查看Linux系统中正在使用的端口。例如&#xff0c;要查看所有正在使用的TCP和UDP端口&#xff0c;你可以运行&#xff1a; sudo netstat -tulpn如果你只想查看所有正在使用的TCP端口&#xff0c;你可以运行&#xff1a; sudo netstat -tpln 如果你只…

全网最最最详细centos7如何安装docker教程

在CentOS 7上安装Docker主要包括以下步骤&#xff1a; 1. 卸载旧版本的Docker 首先&#xff0c;需要确保系统上没有安装旧版本的Docker。可以通过以下命令来卸载它们&#xff1a; sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-late…

【Linux】编译器-gcc/g++使用

个人主页 &#xff1a; zxctscl 文章封面来自&#xff1a;艺术家–贤海林 如有转载请先通知 文章目录 1. 前言2. 初见gcc和g3. 程序的翻译过程3.1 预处理3.1.1 宏替换 去注释 头文件展开3.1.2 条件编译 3.2 编译3.3 汇编3.4 链接 4. 链接4.1 动态链接4.2 静态链接 1. 前言 在之…

吴恩达机器学习-可选实验:特征缩放和学习率(多变量)

文章目录 目标工具概念问题陈述数据集多变量梯度下降学习率a9.9e-7a9e-7a1e-7 特征缩放实现 恭喜致谢 目标 在本实验中&#xff0c;你将: 利用在上一个实验中开发的多变量例程对具有多个特征的数据集运行梯度下降探讨学习率alpha对梯度下降的影响通过使用z-score归一化的特征…

域控操作十:安装包exe转msi软件下发

需要的文件 Advanced Installer 软件用来将exe转换成msi因为域控只能下发msi格式 一个exe安装包这里拿微信举例 一个没有密码的共享文件夹 1.exe转MSI 2&#xff0c;开始下发 服务器和用户刷新策略 #完成