位图

例题1

给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在 这40亿个数中。

首先肯定不能用传统的int数据存储 因为内存不够 40亿的整数大概为16G左右

思路1: 因为byte位数据小 1字节就有8个byte 那么40亿byte数据大概只有500mb左右

    template//先开好总有数据大小
    class moxuan_bit
    {
    public:
        //开空间
        moxuan_bit()
        {
            //char类型有8个字节  所以N个数据就/8即可  假如开10 只开了一个char  不够 所以
            //要+1
            _bits.resize(N / 8 + 1, 0);
        }

        //把x映射的位置标记成1  表示存在
        void set(size_t x)
        {
            //计算在第几个char范围内
            size_t i = x / 8;

            //计算在第i个char范围内的第几个
            size_t j = x % 8;

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

        void reset(size_t x)
        {
            //计算在第几个char范围内
            size_t i = x / 8;

            //计算在第i个char范围内的第几个
            size_t j = x % 8;

            //将第j个数改为1  然后取反  其他bit位变为1  j的数变为0
            //这时候 按位与  其他比特位为不变  j的比特位为0  就删除了这个值不存在
            _bits[i] &= (~(1 << j));
        }

        bool test(size_t x)
        {
            //计算在第几个char范围内
            size_t i = x / 8;

            //计算在第i个char范围内的第几个
            size_t j = x % 8;

            //如果跟1是相同 就返回1 true  如果跟1不相同 就返回0 false
            //并且不是&= 不会改变里面的值
            return _bits[i] & (1 << j);

        }

    private:
        std::vector<char> _bits;
    };

位图

测试:

    void test1()
    {
        moxuan_bit<100> v;
        v.set(20);
        v.set(77);
        v.set(0);

        cout << v.test(20) << " " << v.test(77) << " " << v.test(0) << endl;

        v.reset(0);

        cout << v.test(20) << " " << v.test(77) << " " << v.test(0) << endl;
    }

例题2:

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

思路 :用两个位图表示 大概数据量为 1G

template
    class two_bit
    {
    public:
        void set(size_t x)
        {
            //返回它的状态 1或 0
            int in1 = bit1.test(x);
            int in2 = bit2.test(x);
            //当两个都为0 状态改为 0 1
            if (in1 == 0 && in2 == 0)
            {
                bit2.set(x);
            }
            //当为 01 存在时 又遇到了  就改为 10  表示存在1次以上
            else if(in1==0&&in2==1)
            {
                bit1.set(x);
                bit2.reset(x);
            }
        }

        //如果该值为  0 1 表示就存在过一次
        bool is_once(size_t x)
        {
            return bit1.test(x) == 0 && bit2.test(x) == 1;
        }

    private:
        //用两个位图表示3种状态   0  0 表示不存在 0 1 表示存在一次 1 0 表示存在一次以上
        moxuan_bit bit1;
        moxuan_bit bit2;
    };

测试:

    void test2()
    {
        two_bit<13> v1;
        int a[] = { 5,8,9,2,5,9,4,2,1,0,7,6,5 };

        for (auto e : a)
        {
            v1.set(e);
        }

        for (int i = 0; i 10; i++)
        {
            if (v1.is_once(i))
            {
                cout << i << " ";
            }
        }
    }

&按位与
按位”与”运算符 (&) 会将第一操作数的每一位与第二操作数的相应位进行比较。如果两个位均为 1,则对应的结果位将设置为 1。否则,将对应的结果位设置为 0。
| 按位或:
按位”与或”运算符 (|) 将第一个操作数的每个位与第二个操作数的对应位进行比较。如果其中一个位是 1,则将对应的结果位设置为 1。否则,将对应的结果位设置为 0。
^ 按位异或:
按位”异或”运算符 (^) 将第一操作数的每个位与第二操作数的相应位进行比较。如果一个位是 0,另一个位是 1,则相应的结果位将设置为 1。否则,将对应的结果位设置为 0。
~取反:
若操作数为1 设置为0 若为1 则设置为1
>>右移 实际不是向右移动 而是向低位移动
<

Original: https://www.cnblogs.com/LonelyMoNan/p/16697538.html
Author: lemon-Breeze
Title: 位图

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/607395/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Linux命令行如何实现sftp限速传输

    上周遇到一个需要在Linux命令行模式下进行sftp限速传输的场景(公司带宽占用限制) 百度后无果,问老江湖F哥也没办法(百度出的结果都是用lftp指令,内网环境无法安装) 我真的…

    Linux 2023年5月27日
    090
  • Shell脚本8种字符串截取方法总结

    Linux 的字符串截取很有用。有八种方法。 假设有变量 var=http://www.aaa.com/123.htm. 1. # 号截取,删除左边字符,保留右边字符。 echo …

    Linux 2023年5月28日
    0152
  • Python之–paramiko实例

    一.基于SFTPClient类连接sshd服务器: 特点: 一般用于实现对远程服务器的上传, 下载和对远程目录文件的操作 1 import pramiko 2 3 hostname…

    Linux 2023年6月6日
    0122
  • 机器学习1

    常见的几种假设检验的实例以及对应python代码实现(包括基于图的效果展示 Z检验 t检验 χ2检验 F检验 熟悉scikit-learn及其相关应用 Numpy Numpy 优势…

    Linux 2023年6月6日
    0101
  • RPA SAP财务内部对账机器人

    bash;gutter:true;【简介】本机器人用于使用SAP软件的集团公司间往来对账前台登录SAP账户和密码,需退出PC微信,输入法切换为英文半角状态。【详细流程】1、清空Ex…

    Linux 2023年6月7日
    0129
  • APACHE快速安装流程梳理

    快速安装开始: 【环境配置1】 yum -y install gcc gcc-c++ wget 保留操作(可跳过): yum -y removeapr-util-devel apr…

    Linux 2023年6月6日
    0101
  • 关于在Python2中使用列表推导式会遇到的问题

    摘自《流畅的Python》第二部分第二章2.2 Python 2.x 中,在列表推导中 for 关键词之后的赋值操作可能会影响列表推导上下文中的同名变量。像下面这个 Python …

    Linux 2023年6月6日
    0111
  • SignalR 如何借助redis 实现跨进程通信

    关于redis的订阅和发布功能,这里讲到比较好https://redisbook.readthedocs.io/en/latest/feature/pubsub.html sign…

    Linux 2023年5月28日
    090
  • 统计算法_探索性统计

    最近不知道写什么了,基本python的各种功能百度一下,都能搜到一大把,最近itchat好像很火,不过对这个不是很感冒,等以后有兴趣或者用的上的时候研究研究准备把统计方面的东西再看…

    Linux 2023年6月6日
    093
  • CH343芯片应用—Windows驱动安装与使用

    CH343属于沁恒第三代USB转串口芯片系列的单串口型号,基于经典版CH340芯片完成技术革新,实现USB转高速异步串口,支持最高6Mbps串口波特率。芯片支持使用厂商提供的VCP…

    Linux 2023年6月7日
    0111
  • MySQL里的那些日志们

    该系列博文会告诉你如何从入门到进阶,从sql基本的使用方法,从MySQL执行引擎再到索引、事务等知识,一步步地学习MySQL相关技术的实现原理,更好地了解如何基于这些知识来优化sq…

    Linux 2023年6月14日
    0110
  • JavaScript快速入门-08-JSON

    8 JSON 因平时工作时,使用JSON的场景比较多,其JSON语法不再介绍,仅介绍在JavaScript中JSON的解析和序列化。 8.1 JSON 对象 JSON对象有两个方法…

    Linux 2023年6月7日
    0110
  • 玩转redis-延时消息队列

    上一篇基于 redis的list实现了一个简单的消息队列:玩转redis-简单消息队列 源码地址 使用demo 产品经理经常说的一句话,我们不光要有 X功能,还要 Y功能,这样客户…

    Linux 2023年5月28日
    0129
  • xshell使用小技巧

    方便复制:Tool –> options –> right buttion(paste the clipboard contents) and …

    Linux 2023年6月7日
    095
  • Jstack排查线上CPU100%

    Jstack排查线上CPU100% 介绍 jstack是JVM自带的Java堆栈跟踪工具,用于生成java虚拟机当前时刻的线程快照,来帮助定位线程出现长时间停顿的原因,例如死锁、死…

    Linux 2023年6月6日
    0110
  • 关于多个 Cookie 的分隔符这件事

    对于 Cookie 的处理上,我最近遇到一个问题,那就是如何分割 Cookie 的内容。有人说是使用逗号分割,有人说是使用分号分割,究竟用哪个才是对的?其实这个答案是需要分为两个过…

    Linux 2023年6月6日
    093
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球