• 位图的实现,布隆过滤器


    位图:

    概念:

    由于位图是通过一个比特位来判断是不是在范围里面的,所以其对应的时间复杂度都是O(1)的。

    位图的实现:

    如上图所示:
    上图对应的就是3个字节,即24个比特位

    要想实现位图,就得知道我们要记录的这个数应该存储到哪个位置,假设这个数是x

    那么对应:

    x / 32 所得的值就是该数字应该存在第几个字节上

    x % 32 所得的值就是对应在此字节的第几位上,这样一来位图就简单了

    我们主要实现 set,reset,test这三个借口,代码如下:

    1. #pragma once
    2. #include
    3. using namespace std;
    4. namespace bit
    5. {
    6. template<size_t N>
    7. class bitset
    8. {
    9. public:
    10. bitset()
    11. {
    12. _a.resize(N / 32 + 1);
    13. }
    14. // x映射的那个标记成1
    15. void set(size_t x)
    16. {
    17. size_t i = x / 32;
    18. size_t j = x % 32;
    19. _a[i] |= (1 << j);
    20. }
    21. // x映射的那个标记成0
    22. void reset(size_t x)
    23. {
    24. size_t i = x / 32;
    25. size_t j = x % 32;
    26. _a[i] &= (~(1 << j));
    27. }
    28. // 判断 x 是否在位图里面
    29. bool test(size_t x)
    30. {
    31. size_t i = x / 32;
    32. size_t j = x % 32;
    33. return _a[i] & (1 << j);
    34. }
    35. private:
    36. vector<int> _a;
    37. };
    38. }

    注意这里模板的应用,是为了开出大小适中的位图出来。

    测试代码:

    位图的应用:

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

    要找到只出现一次的整数,就要让出现一次和出现多次的数有所区别,

    而位图只能存储0或1,所以没法区别,这是就需要用到两个位图:

    只要出现多次,就将其记成10,这样就得以区分

    对应的代码实现:

    1. template<size_t N>
    2. class TwoBitSet1
    3. {
    4. public:
    5. void set(size_t x)
    6. {
    7. // 00 -> 01
    8. if (!_bs1.test(x) && !_bs2.test(x))
    9. {
    10. _bs2.set(x);
    11. }
    12. //01 -> 10
    13. else if (!_bs1.test(x) && _bs2.test(x))
    14. {
    15. _bs1.set(x);
    16. _bs2.reset(x);
    17. }
    18. }
    19. bool is_once(size_t x)
    20. {
    21. return !_bs1.test(x) && _bs2.test(x);
    22. }
    23. private:
    24. bitset _bs1;
    25. bitset _bs2;
    26. };

    测试代码:

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

    解法:

    将两个文件分别映射到两个位图,再将两个位图的值与一下即可:

    对应的代码实现如下:

    1. int main()
    2. {
    3. int a1[] = { 1, 2, 3, 3, 4, 4, 4, 4, 4, 2, 3, 6, 3, 1, 5, 5, 8, 9 };
    4. int a2[] = { 8, 4, 8, 4, 1, 1, 1, 1 };
    5. bit::bitset<10> bs1;
    6. bit::bitset<10> bs2;
    7. for (auto e : a1)
    8. {
    9. bs1.set(e);
    10. }
    11. for (auto e : a2)
    12. {
    13. bs2.set(e);
    14. }
    15. for (int i = 0; i < 10; i++)
    16. {
    17. if (bs1.test(i) && bs2.test(i))
    18. {
    19. cout << i << " ";
    20. }
    21. }
    22. cout << endl;
    23. return 0;
    24. }

    代码测试:

    3.位图应用变形:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数

    其实做法与第一题很像,直接上代码:

    1. template<size_t N>
    2. class TwoBitSet2
    3. {
    4. public:
    5. void set(size_t x)
    6. {
    7. // 00 -> 01
    8. if (!_bs1.test(x) && !_bs2.test(x))
    9. {
    10. _bs2.set(x);
    11. }
    12. //01 -> 10
    13. else if (!_bs1.test(x) && _bs2.test(x))
    14. {
    15. _bs1.set(x);
    16. _bs2.reset(x);
    17. }
    18. //10 -> 11
    19. else if (_bs1.test(x) && !_bs2.test(x))
    20. {
    21. _bs2.set(x);
    22. }
    23. }
    24. bool is_once(size_t x)
    25. {
    26. return !_bs1.test(x) && _bs2.test(x);
    27. }
    28. bool is_twice(size_t x)
    29. {
    30. return _bs1.test(x) && !_bs2.test(x);
    31. }
    32. private:
    33. bitset _bs1;
    34. bitset _bs2;
    35. };

    测试代码:

    库里面的位图接口:

    布隆过滤器

    概念:

    只能确定其一定不存在或者可能存在,注意可能二字

    所以说布隆过滤器不能准确判断一个东西是否存在。

    应用:

    1.不需要精确的场景,快速判断昵称是否存在

    2.精确的场景,布隆过滤器

  • 相关阅读:
    VirtualBox配置Centos7双网卡固定IP
    中国领先世界的机会稍纵即逝
    11、vector容器
    一篇文章让你搞懂线程
    php学习笔记
    【Python自动化办公】分享几个好用到爆的模块,建议收藏
    STM32与物联网02-网络数据收发
    (附源码)计算机毕业设计SSM竞赛报名管理系统
    tensor的索引、切片、拼接和压缩等
    Unity il2cpp API 调用实践
  • 原文地址:https://blog.csdn.net/m0_61497245/article/details/133132005