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映射的哪个标记映射成为1
        void set(size_t x)
        {
            size_t i = x / 32;
            size_t j = x % 32;
            a_[i] |= (1 << j); // 小端机,开头就是低位,所以直接左移j位
        }
        // 将x映射的哪个标记映射成为0
        void 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));
                else
                    hash ^= (~((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进行读取,存在缓存命中问题;

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙开发-UI-动画-页面内动画

鸿蒙开发-UI-组件2 鸿蒙开发-UI-组件3 鸿蒙开发-UI-气泡/菜单 鸿蒙开发-UI-页面路由 鸿蒙开发-UI-组件导航-Navigation 鸿蒙开发-UI-组件导航-Tabs 鸿蒙开发-UI-图形-图片 鸿蒙开发-UI-图形-绘制几何图形 鸿蒙开发-UI-图形-绘制自定义图形 文章目录 前言 一、概述 二、页面内…

基于springboot+vue的美食烹饪互动平台

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

Ainx的消息封装

&#x1f4d5;作者简介&#xff1a; 过去日记&#xff0c;致力于Java、GoLang,Rust等多种编程语言&#xff0c;热爱技术&#xff0c;喜欢游戏的博主。 &#x1f4d7;本文收录于Ainx系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏Rust初阶教程、go语言基础系列…

【深度学习笔记】6_9 深度循环神经网络deep-rnn

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;部分标注了个人理解&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 6.9 深度循环神经网络 本章到目前为止介绍的循环神经网络只有一个单向的隐藏层&#xff0c;在深度学习应用里&#xff0c;我们通常会用…

宿主机连接不上vmware中的虚拟机排查思路

1、简介 在前文中&#xff0c;我们遇到了电脑连接网络后无法浏览网页的情况&#xff0c;其中有一种方式就是将网络适配器卸载&#xff0c;然后重启机器。今天在使用vmware中的虚拟机时&#xff0c;发现和宿主机网段不一致&#xff0c;导致宿主机访问不了虚拟机&#xff0c;主要…

Vue快速开发一个主页

前言 这里讲述我们如何快速利用Vue脚手架快速搭建一个主页。 页面布局 el-container / el-header / el-aside / el-main&#xff1a;https://element.eleme.cn/#/zh-CN/component/container <el-container><el-header style"background-color: #4c535a"…

【算法沉淀】最长回文子串

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《数据结构与算法&#xff1a;初学者入门指南》&#x1f4d8;&am…

探索代理服务器:保护您的网络安全与隐私

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Linux ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 隐藏真实IP地址&#xff1a; 访问控制&#xff1a; 加速访问速度&#xff1a; 过滤内容&#xff1a; 突破访问限制&#xff1…

【Linux系统】线程

目录 一.线程的概念 (1)地址空间是进程的资源窗口 (2)轻量级进程 二.线程的理解 1.Linux中线程的实现方案 2. 线程VS进程 3.线程比进程更加轻量化 4.线程的优点 5.线程的缺点 6.线程共享的资源 7.线程私有的资源 三.地址空间虚拟到物理的转化 1.页框 2.重新理解文…

Vessel - Linux hackthebox

#hard #runc #RE #Nodejs-SQLI Enumeration .git leak 使用 dumpall 下载 .git 打开 routes/index.js 可以看到网站使用 nodejs mysql 编写&#xff0c;且只有登录功能 router.post(/api/login, function(req, res) {let username req.body.username;let password req…

深入理解神经网络

图片怎么被识别的过程 (每层神经网络是数组,会对进来的数据进行加权求和[(weight*数据 然后累加) bias])(激活函数是为了训练weight和bias偏移值,在每个神经网络)(分类器会统计概率分类) 2. 引用链接 https://mp.weixin.qq.com/s?__bizMzIyNjMxOTY0NA&mid2247500124&…

springboot256基于springboot+vue的游戏交易系统

游戏交易系统设计与实现 摘 要 在如今社会上&#xff0c;关于信息上面的处理&#xff0c;没有任何一个企业或者个人会忽视&#xff0c;如何让信息急速传递&#xff0c;并且归档储存查询&#xff0c;采用之前的纸张记录模式已经不符合当前使用要求了。所以&#xff0c;对游戏交…

就业班 2401--3.8 Linux Day14--阿帕奇+LNMP(编译安装)

一、WEB服务器 ^世上最重要的事&#xff0c;不在于我们在何处&#xff0c;而在于我们朝着什么方向走。^ 1、WEB服务简介 # 目前最主流的三个Web服务器是Apache、Nginx、 IIS。 - WEB服务器一般指网站服务器&#xff0c;可以向浏览器等Web客户端提供网站的访问&#xff0c;让全…

C语言字符串、字符数组与字符串常量——各种奇奇怪怪的偏难怪

文章目录 一、字符串二、字符数组三、字符串常量&#xff08;字符指针&#xff09;易错点总结 一、字符串 在C语言中&#xff0c;没有专门的字符串变量&#xff0c;没有string类型。 字符串定义有两种方法&#xff1a;一是利用字符数组&#xff0c;二是利用字符指针 。 字符串…

计算机考研|一个很上头的408复习法(可实操)

因为408越复习&#xff0c;越轻松&#xff0c;这就是408上头的原因 408一开始复习肯定是有难度的&#xff0c;这也是408非常劝退的原因之一&#xff0c;但是如果你是科班出身&#xff0c;学完408第一遍之后&#xff0c;你就会轻松很多&#xff0c;因为408的内容虽然多&#xf…

详解数据库、Hive以及Hadoop之间的关系

1.数据库&#xff1a; 数据库是一个用于存储和管理数据的系统。数据库管理系统&#xff08;DBMS&#xff09;是用于管理数据库的软件。数据库使用表和字段的结构来组织和存储数据。关系型数据库是最常见的数据库类型&#xff0c;使用SQL&#xff08;Structured Query Language…

【决策树】预测用户用电量

决策树预测用户用电量 文章目录 决策树预测用户用电量  &#x1f449;引言&#x1f48e;一、 数据预处理数据预处理初步数据分析 二、 机器学习算法决策树回归预测用电量决策树模型介绍&#xff1a;回归预测 三、 可视化结果四、 数据分析与结论代码如下 &#x1f449;引言&a…

如何快速分析OB集群日志,敏捷诊断工具obdiag分析能力实践——《OceanBase诊断系列》之四

1. 前言 obdiag是OceanBase的敏捷诊断工具。1.2版本中&#xff0c;obdiag支持快速收集诊断信息&#xff0c;但仅有收集能力是不够的&#xff0c;还需要有分析能力。因此在obdiag的1.3.0版本中&#xff0c;我们加入了OB集群的日志分析功能。用户可以一键进行集群的OB日志的分析…

arcgis 栅格数据处理2——栅格转地级市(栅格转矢量图)

1. 获取空间分析权限&#xff08;解决无法执行所选工具问题&#xff09; 选中“自定义”中的“扩展模块” 在弹出的模块中选中能选的模块&#xff0c;此处需要选择“spatial analysis”以进行下一步分析 3. 将栅格数据转为整数型&#xff08;解决无法矢量化&#xff09; 选…

弹性布局(下),过渡

弹性布局 1.当子元素在主轴方向的长度和大于父元素的情况 子元素在父元素中放不下是否换行&#xff1f; flex-warp&#xff1a; 默认值&#xff1a; nowrap 不换行&#xff0c;压缩子元素的长度&#xff0c;最常用 可选值&#xff1a; wrap 换行 当子元素被压缩时&#xff0…