zoukankan      html  css  js  c++  java
  • Bitmap

    什么是bitmap?

    来自于《编程珠玑》。所谓的Bit-map就是用一个bit位来标记某个元素对应的Value, 而Key即是该元素。由于采用了Bit为单位来存储数据,因此在存储空间方面,可以大大节省。
     
    举个例子。我们要存储3,4,5,6,7这几个元素。如果用int[]来存储的话,我们需要5*32bit。我们知道int32默认值是0,它是由32个0组成的。这样的话我们能不能用它的每个bit位来存储一个数字呢?1-32位代表1-32这32个数字。而0代表不存在、1代表存在。这样的话,我们一个int32就可以存储32个数字了。话不多说,马上开搞。其实原理都非常简单~
     
       static void Main(string[] args)
            {
                BitMap map = new BitMap();
                map.Add(11);
                map.Add(22);
                map.Add(3);
                map.Add(7);
                map.Add(6);
                foreach (var item in map)
                {
                    Console.WriteLine(item);
                }
            }
    
            public class BitMap : IEnumerable<int>
            {
                private int[] _bucket;
                public BitMap()
                {
                    _bucket = new int[10];
                }
    
                private void Expand(int count)
                {
                    var temp = new int[count];
                    _bucket.CopyTo(temp, 0);
                    _bucket = temp;
                }
    
                public void Add(int value)
                {
                    int index = (value - 1) / 32;//得到在bucket中的下标
                    if (index + 1 > _bucket.Length)//如果bucket太小,就进行扩充
                    {
                        Expand(index + 1);
                    }
                    var item = _bucket[index];//获得对应位置中的元素
                    var binary = Convert.ToString(item, 2).PadLeft(32, '0').Select(x => x.ToString()).ToList();//将item转换成2进制的字符串,再转换为list
                    int bitindex = (value - 1) % 32;
                    binary[bitindex] = "1";
                    var binarystr = binary.Aggregate((x, y) => x + y);
                    var result = Convert.ToInt32(binarystr, 2);
                    _bucket[index] = result;
                }
    
                public IEnumerator<int> GetEnumerator()
                {
                    for (int i = 0; i < _bucket.Length; i++)
                    {
                        var item = _bucket[i];
                        if (item == 0)
                            continue;
                        string binary = Convert.ToString(item, 2).PadLeft(32, '0');
                        for (int j = 0; j < binary.Length; j++)
                        {
                            if (binary[j] == '1')
                            {
                                yield return i * 32 + j + 1;
                            }
                        }
                    }
                }
    
                System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
                {
                    throw new NotImplementedException();
                }
            }

    这样我们的bitmap就已经构造完成了。

    当然,如果你懂位运算的话,我们还可以改成这样

      static void Main(string[] args)
            {
                BitMap map = new BitMap();
                map.Add(11);
                map.Add(22);
                map.Add(3);
                map.Add(7);
                map.Add(6);
                foreach (var item in map)
                {
                    Console.WriteLine(item);
                }
            }
    
            public class BitMap : IEnumerable<int>
            {
                private int[] _bucket;
                public BitMap()
                {
                    _bucket = new int[10];
                }
    
                private void Expand(int count)
                {
                    var temp = new int[count];
                    _bucket.CopyTo(temp, 0);
                    _bucket = temp;
                }
    
                public void Add(int value)
                {
                    int index = (value - 1) / 32;//得到在bucket中的下标
                    if (index + 1 > _bucket.Length)//如果bucket太小,就进行扩充
                    {
                        Expand(index + 1);
                    }
                    var item = _bucket[index];//获得对应位置中的元素
                    int bitindex = (value - 1) % 32;//计算获得需要将哪个bit位置为1
                    item = item | (1 << (31 - bitindex));//将对应的位置置为1
                    _bucket[index] = item;
                }
    
                public IEnumerator<int> GetEnumerator()
                {
                    for (int i = 0; i < _bucket.Length; i++)
                    {
                        var item = _bucket[i];
                        if (item == 0)
                            continue;
                        for (int j = 0; j < 32; j++)
                        {
                            var step = 31 - j;
                            var temp = 1 << step;
                            if ((item & temp) == 0)
                                continue;
                            var result = i * 32 + j + 1;
                            yield return result;
                        }
                    }
                }
    
                System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
                {
                    throw new NotImplementedException();
                }
            }

    其实2组代码的实现效果都是一样的。但位运算是直接操作'位'的。所以性能会高点。

    当然,bitmap也有缺点,如果有2个相同的元素,它没办法了。因为bit不是0就是1。

     
  • 相关阅读:
    顶目群定义及项目群管理
    项目管理与项目组合管理的不同
    IT项目经理:人际关系技能和领导技能的重要性
    IT 项目经理的职业生涯
    Sharepoint2010 中隐藏 "快速启动"与"最近修改'
    3 个基本的IT项目组合种类
    项目成功的标志及决定因素
    HDL,你们作对了吗?
    JAVA代码编写的30条建议
    八款开源 Android 游戏引擎
  • 原文地址:https://www.cnblogs.com/irenebbkiss/p/4650495.html
Copyright © 2011-2022 走看看