• Bitmap vs 2Bitmap的实现


    【本文链接】

    http://www.cnblogs.com/hellogiser/p/bitmap-vs-2bitmap.html

    【题目】

    在2.5亿个整数找出不重复的整数,内存不足以容纳着2.5亿个整数

    【分析】

    Bitmap就是用一个bit位来标记某个元素是否存在,而2Bitmap就是用两个bit为来标记某个元素的个数,00,01,10,11(分别表示0,1,2,3,0表示不存在,1表示存在1次,后面依次)。

    整数可能是正数也可能是负数,首先只考虑正整数情况,采用2Bitmap方法,用00表示不存在,01表示出现1次,10表示出现2次及以上,此方法总共需要的内存2^31*2bit = 1Gb = 128MB(32位的正整数有2^31个,每个存储需要2bit,所以就是1Gb,换成字节就是128MB),这样内存就应该能够容纳了,最后在处理完所有的数后,只要输出对应位为01的数即可。如果这2.5亿个数里面既有正数又有负数那么就用两个2Bitmap分别存储正数和负数(取绝对值存储),零就随便放,所需要的内存是512MB。

    【代码】

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
     
    /*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/10/8
    */


    #include "stdafx.h"
    #include <iostream>
    using namespace std;

    class BitSet
    {
    public:
        BitSet (
    int range)
        {
            
    // [0,range)
            m_nRange = range;
            m_nLength = m_nRange / 
    32 + 1;

            bitset = 
    new int[m_nLength];
            
    // init all with 0
            for (int i = 0; i < m_nLength; i++)
            {
                bitset[i] = 
    0;
            }
        }

        ~BitSet()
        {
            
    delete []bitset;
        }

        
    void Set(int number)
        {
            
    int i = number / 32;
            
    int j = number % 32;
            bitset[i] |= (
    1 << j);
        }

        
    int Get(int number)
        {
            
    int i = number / 32;
            
    int j = number % 32;
            
    return (bitset[i] & (1 << j)) >> j;
        }

        
    void Output()
        {
            
    for (int i = 0; i < m_nRange; i++)
            {
                
    if (Get(i))
                {
                    cout << i << 
    " ";
                }
            }
            cout << endl;
        }
    private:
        
    int *bitset;
        
    int m_nRange; // range of numbers
        int m_nLength; // len of array
    };

    class BitSet1
    {
    public:
        BitSet1 (
    int range)
        {
            
    // [0,range)
            //default value
            m_nBitWidth = 1;
            m_nWord = 
    32 / m_nBitWidth;


            m_nRange = range;
            m_nLength = m_nRange / m_nWord + 
    1;

            bitset = 
    new int[m_nLength];
            
    // init all with 0
            for (int i = 0; i < m_nLength; i++)
            {
                bitset[i] = 
    0;
            }
        }

        ~BitSet1()
        {
            
    delete []bitset;
        }

        
    void Set(int number)
        {
            
    int i = number / m_nWord;
            
    int j = number % m_nWord;
            bitset[i] |= (
    1 << j);
        }

        
    void Clear(int number)
        {
            
    int i = number / m_nWord;
            
    int j = number % m_nWord;
            bitset[i] &= ~(
    1 << j);
        }

        
    int Get(int number)
        {
            
    // return count of number
            int i = number / m_nWord;
            
    int j = number % m_nWord;
            
    return (bitset[i] & (1 << j)) >> j;
        }

        
    void Output()
        {
            
    for (int i = 0; i < m_nRange; i++)
            {
                
    if (Get(i))
                {
                    cout << i << 
    " ";
                }
            }
            cout << endl;
        }
    private:
        
    int m_nBitWidth;// 1 2 3
        int m_nWord; // word = 32/BitWidth
        /*  1: 0,1
            2: 00,01,10,11
            3: 000,...111
        */


        
    int *bitset;
        
    int m_nRange; // range of numbers
        int m_nLength; // len of array
    };


    class BitSet2
    {
    public:
        BitSet2 (
    int range)
        {
            
    // [0,range)
            //default value
            m_nBitWidth = 2;// 1,2,3
            m_nWord = 32 / m_nBitWidth; //32, 16,8
            m_nMaxCount = 1 << m_nBitWidth; //1,3,7

            m_nRange = range;
            m_nLength = m_nRange / m_nWord + 
    1;

            bitset = 
    new int[m_nLength];
            
    // init all with 0
            for (int i = 0; i < m_nLength; i++)
            {
                bitset[i] = 
    0;
            }
        }

        ~BitSet2()
        {
            
    delete []bitset;
        }

        
    void Add(int number)
        {
            
    int count = Get(number);
            __Set(number, count + 
    1);
        }

        
    void __Set(int number, int count)
        {
            
    if(count > 3)
                
    return;
            
    //clear first
            Clear(number);

            
    // then set
            int i = number / m_nWord;
            
    int j = number % m_nWord;
            bitset[i] |= ((
    3 & count) << 2 * j);
        }

        
    void Clear(int number)
        {
            
    int i = number / m_nWord;
            
    int j = number % m_nWord;
            bitset[i] &= ~(
    3 << (2 * j));
        }

        
    int Get(int number)
        {
            
    // return count of number
            int i = number / m_nWord;
            
    int j = number % m_nWord;
            
    return (bitset[i] & (3 << (2 * j))) >> (2 * j);
        }

        
    void Output()
        {
            
    for (int i = 0; i < m_nRange; i++)
            {
                
    if (Get(i))
                {
                    cout << i << 
    " ";
                }
            }
            cout << endl;
        }
    private:
        
    int m_nBitWidth;// 1 2 3
        int m_nWord; // word = 32/BitWidth
        /*  1: 0,1
            2: 00,01,10,11
            3: 000,...111
        */

        
    int m_nMaxCount; // 1,11,111===>1,3,7

        
    int *bitset;
        
    int m_nRange; // range of numbers
        int m_nLength; // len of array
    };


    void test_default1(int *a, int len, int range)
    {
        cout << 
    "===Bitset1===" << endl;
        BitSet1 bs1(range);
        
    for (int i = 0; i < len; i++)
        {
            bs1.Set(a[i]);
        }

        
    for (int i = 0; i < range; i++ )
        {
            cout << i << 
    " count = " << bs1.Get(i) << endl;
        }
    }

    void test_case1()
    {
        
    int a[] = {1223334444578};
        
    int range = 10;
        test_default1(a, 
    sizeof(a) / 4, range);
    }

    void test_default2(int *a, int len, int range)
    {
        cout << 
    "===Bitset2===" << endl;
        BitSet2 bs2(range);
        
    for (int i = 0; i < len; i++)
        {
            bs2.Add(a[i]);
        }

        
    for (int i = 0; i < range; i++ )
        {
            cout << i << 
    " count = " << bs2.Get(i) << endl;
        }
    }


    void test_case2()
    {
        
    int a[] = {1223334444578};
        
    int range = 10;
        test_default2(a, 
    sizeof(a) / 4, range);
    }

    int main()
    {
        test_case1();
        test_case2();
        
    return 0;
    }
    /*
    ===Bitset1===
    0 count = 0
    1 count = 1
    2 count = 1
    3 count = 1
    4 count = 1
    5 count = 1
    6 count = 0
    7 count = 1
    8 count = 1
    9 count = 0
    ===Bitset2===
    0 count = 0
    1 count = 1
    2 count = 2
    3 count = 3
    4 count = 3
    5 count = 1
    6 count = 0
    7 count = 1
    8 count = 1
    9 count = 0
    */

    【其它题目】

    1.给40亿个不重复的unsigned int的整数,没排过序的,然后再给几个数,如何快速判断这几个数是否在那40亿个数当中?

    unsigned int 的取值范围是0到2^32-1。我们可以申请连续的2^32/8=512M的内存,用每一个bit对应一个unsigned int数字。首先将512M内存都初始化为0,然后每处理一个数字就将其对应的bit设置为1。当需要查询时,直接找到对应bit,看其值是0还是1即可。

    2.有1到10w这10w个数,去除2个并打乱次序,如何找出那两个数?
    申请10w个bit的空间,每个bit代表一个数字是否出现过。开始时将这10w个bit都初始化为0,表示所有数字都没有出现过。然后依次读入已经打乱循序的数字,并将对应的bit设为1。当处理完所有数字后,根据为0的bit得出没有出现的数字。

    【参考】

    http://blog.csdn.net/jirongzi_cs2011/article/details/9331003

    http://www.cnblogs.com/pangxiaodong/archive/2011/08/14/2137748.html

    http://blog.csdn.net/acceptedxukai/article/details/9025493

    http://blog.csdn.net/zhulei632/article/details/6701868

  • 相关阅读:
    hbase深入了解
    Android SDK安装与环境变量配置以及开发第一个Android程序
    Android平台架构及特性
    android Notification定义与应用
    Windows Phone 7 开发 31 日谈——第1日:项目模板
    MVC HtmlHelper类的方法总结(转)
    INotifyPropertyChanged的使用
    浅谈计算机软件的破解与保护(时间:20111224作者:李富云 来源:中国论文库)
    托管代码&非托管代码
    .net也疯狂:生成zip文件(转)
  • 原文地址:https://www.cnblogs.com/hellogiser/p/bitmap-vs-2bitmap.html
Copyright © 2020-2023  润新知