• C++:位图


    目录

    一.位图

    位图应用题1:

    set 增加值:

    位图题1代码:

    位图应用题2:给定100亿个整数,设计算法找到只出现一次的整数?

    二.布隆过滤器

    1.概念

    2.布隆过滤器删除

    3.应用场景

    4.哈希切割


    一.位图

    位图应用题1:

    给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在
    这40亿个数中。【腾讯】
    40亿个整数,占用多少空间:16G:40 0000 0000 * 4=160 0000 0000 byte字节=16G
    1G 等于 2^30 约等于 10亿字节

    1、set/unordered set? 内存不够
    2、外排序+二分查找? 不能很好支持快速随机访问 ,这两种都不行

     
    3. 位图解决

    位图:直接定址法哈希---用一个比特位标识映射值在不在

    方法:

    数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一
    个二进制比特位来代表数据是否存在的信息,如果二进制比特位为 1 ,代表存在,为 0
    代表不存在。比如:

    原本4个字节存一个数,现在1个bit存一个数的状态,1字节=8bit,4字节=32bit,16G/32=500MB,现在消耗500MB即可

    set 增加值:

    1. //x映射的位标记成1
    2. void set(size_t x) //增加x到这些数中,把x对应的比特位设置为1
    3. {
    4. // x映射的比特位在第几个char对象
    5. size_t i = x / 8;
    6. // x在char第几个比特位
    7. size_t j = x % 8;
    8. _bits[i] |= (1 << j);
    9. }

    位图题1代码:

    1. #pragma once
    2. #include
    3. namespace bit
    4. {
    5. // N个比特位的位图 10 16
    6. template<size_t N> //总的数的数量,这里设成100先
    7. class bitset
    8. {
    9. public:
    10. bitset()
    11. {
    12. // +1保证足够比特位,最多浪费8个
    13. _bits.resize(N/8 + 1, 0);
    14. }
    15. //x映射的位标记成1
    16. void set(size_t x) //增加x到这些数中,把x对应的比特位设置为1
    17. {
    18. // x映射的比特位在第几个char对象
    19. size_t i = x / 8;
    20. // x在char第几个比特位
    21. size_t j = x % 8;
    22. _bits[i] |= (1 << j);
    23. }
    24. void reset(size_t x) //删除x,把x对应的比特位设置为0
    25. {
    26. // x映射的比特位在第几个char对象
    27. size_t i = x / 8;
    28. // x在char第几个比特位
    29. size_t j = x % 8;
    30. //! && ||
    31. //~ & |
    32. _bits[i] &= (~(1 << j));
    33. }
    34. bool test(size_t x)
    35. {
    36. // x映射的比特位在第几个char对象
    37. size_t i = x / 8;
    38. // x在char第几个比特位
    39. size_t j = x % 8;
    40. return _bits[i] & (1 << j);
    41. }
    42. private:
    43. std::vector<char> _bits;
    44. //vector _bits;
    45. };
    46. void test_bit_set1()
    47. {
    48. bitset<100> bs;
    49. bs.set(18);
    50. bs.set(19);
    51. cout << bs.test(18) << endl;
    52. cout << bs.test(19) << endl;
    53. cout << bs.test(20) << endl;
    54. bs.reset(18);
    55. bs.reset(18);
    56. cout << bs.test(18) << endl;
    57. cout << bs.test(19) << endl;
    58. cout << bs.test(20) << endl;
    59. //bitset bigBS;
    60. bitset<0xFFFFFFFF> bigBS;
    61. //bitset<-1> bigBS;
    62. //bit_set<2^32-1> bigBS; // pow
    63. }
    64. }

    位图应用题2:给定100亿个整数,设计算法找到只出现一次的整数?

    方法:用两个 bitset 数组  _bs1,_bs2记录,x对应两个数组的比特位来记录这个数出现的次数,_bs1对应比特位是0,_bs2对应比特位是0,就是出现0次;_bs1对应比特位是0,_bs2对应比特位是1,就是出现1次;_bs1对应比特位是1,_bs2对应比特位是0,就是出现2次;

    1. #pragma once
    2. #include
    3. namespace bit
    4. {
    5. template<size_t N>
    6. class two_bitset
    7. {
    8. public:
    9. void set(size_t x)
    10. {
    11. int in1 = _bs1.test(x);
    12. int in2 = _bs2.test(x);
    13. if (in1 == 0 && in2 == 0)
    14. {
    15. _bs2.set(x);
    16. }
    17. else if (in1 == 0 && in2 == 1)
    18. {
    19. _bs1.set(x);
    20. _bs2.reset(x);
    21. }
    22. }
    23. bool is_once(size_t x)
    24. {
    25. return _bs1.test(x) == 0 && _bs2.test(x) == 1;
    26. }
    27. private:
    28. bitset _bs1;
    29. bitset _bs2;
    30. };
    31. void test_two_bitset()
    32. {
    33. int a[] = { 4, 3, 2, 4, 5, 2, 2, 4, 7, 8, 9, 2, 1,3,7 };
    34. two_bitset<10> tbs;
    35. for (auto e : a)
    36. {
    37. tbs.set(e);
    38. }
    39. for (size_t i = 0; i < 10; ++i)
    40. {
    41. if (tbs.is_once(i))
    42. {
    43. cout << i << endl;
    44. }
    45. }
    46. }
    47. }

    二.布隆过滤器

    1.概念

    布隆过滤器: 将哈希与位图结合,即布隆过滤器。它是用多个哈希函数,将一个数据映射到位图结构中

    无法解决哈希冲突
    存在冲突既是误判——在:存在误判。不在:是准确的,这个数据只要有一个映射值不在就一定不在。
    给出几个网址ip形式的字符串,set添加数据:通过不同的函数将字符串转换成整数记录在哈希表上,这里假设只用了3个不同函数进行映射,比如 123.0.3.22 这个字符串映射3个数:100 33 22,set(123.0.3.22 ) 以后就加入这3个数。

    test查看:假如下面前3个字符串都set了,若test查看第2个字符串 192.0.3.21 是否存在,则看对应的映射值 23 33 99 是否都存在,都在就说明已经set过了,存在,但是还是有误判的可能,只不过函数越多,误判的概率越小。比如:test查看第4个字符串:

    若test查看第4个字符串 31.22.1.1 是否存在,则看对应的映射值 55 88 70是否都存在,比如查55存在,和第3个重了;查88存在,和第3个重了;查70不存在,说明没有这个字符串,所以  31.22.1.1不存在。

    2.布隆过滤器删除

    布隆过滤器不能直接支持删除工作,因为在删除一个元素时,可能会影响其他元素。
    一种支持删除的方法:将布隆过滤器中的每个比特位扩展成一个小的计数器,插入元素时给 k 个计
    数器 (k 个哈希函数计算出的哈希地址 ) 加一,删除元素时,给 k 个计数器减一,通过多占用几倍存储
    空间的代价来增加删除操作。
    缺陷:
    1. 无法确认元素是否真正在布隆过滤器中
    2. 存在计数回绕

    删除一个值,只需要——映射位置的计数
    删除这个值以后,可能存在判断他还在! -- 误判
    布隆过滤器的特点节省空间,支持删除就不那么节省了

    3.应用场景

    (1)注册的时候,快速判断一 个昵称是否使用过?
    a、不在:没有用过 绿色对钩
    b、在:再去数据库查确认一遍

    (2)黑名单
    a、不在        就通行
    b、在 就再次去系统确认

    (3)过滤层,提高查找数据效率

    a、不在        就返回
    b、在 就再次去数据系统找一遍

    这样不在的情景就效率极高

    4.哈希切割

    题目:给一个超过100G大小的log file, log中存着IP地址,设计算法找到出现次数最多的IP地址?

    (1)统计次数,如何统计次数?

    平分100个文件,统计次数是不对的。因为相同ip可能分到不同的文件中去了

    正确做法:

    哈希切割(分):利用哈希函数得出字符串对应的映射值 i,把这个字符串放到对应的 Ai文件中,则相同的ip,一定进入同一个小文件

  • 相关阅读:
    3--OpenCV:图像色彩模型转换
    GBase 8a MPP集群性能监控
    深入解析HTTP(web开发详细理解原理)【JavaWeb】
    MySQL项目迁移华为GaussDB PG模式指南
    我国有多少个港口?
    .NET 7 AOT 的使用以及 .NET 与 Go 互相调用
    编写基础程序:Hello World
    SSM框架介绍
    数据要素与多元市场主体融合机制研究
    算法——单调队列
  • 原文地址:https://blog.csdn.net/zhang_si_hang/article/details/126847364