BitMap:算法思想基础曲解

之前看到关于缓存击穿相关文章时,  延伸到了布隆过滤器和bitmap算法。

验证了解之后,觉得应该写下了,不然总是遗忘。

所谓BitMap就是用一个bit位来标记元素的值。

这句话咋理解捏?我们来慢慢分析!

一:

        举个栗子,来具象了解算法原理,假如有这么几个随机数,前提是不重复,int arr[]={4,7,11,2,5},如何

将这几个标记在bitmap中呢?

       开始;

在java中一个最小存储单位为byte(子节),1byte=8bit,新建一个byte数组,byte[]  bits=new byte[2];   那么arr中的元素

在bits中的标记就如下图:(新建两个byte数组,每个byte的bit位都置为0,0表示未出现,1表示出现,这里默认为Little-ending)

看完这张图,大概知道bitmap的基本原理,bit位所在下标就是值的表达,是不是很神奇?

一个int类型数据占4个byte也就是32bit而用bitmap来表示只需要一个bit,理论上是缩减了32倍的空间。

      看到这新的问题出现,那通过怎样的计算,来实现标记呢?其实就是和8这个数字相关的运算,因为一个byte有8个bit啊!

如果我们的数字不超过7那就好办了,一个byte就搞定了,怎样确定位置呢?

position=N%8  N呢就是我们的目标数,%8找到下标位置。

但是,现实中数字可不是只有到7 ,当目标数为8的时候呢?  发现下标也为0,这是不是相当于占据了目标0的位置呢?

看看上图,其实并不是,按照bitmap的算法,8应该是占据第二个byte的0的位置。

所以我们需要第二个关键位置,就是目标数字所在的byte的[index]   ,很简单index=N/8=N>>3。

当两个关键位置都有了,我们就可以个写一个简单的bitmap类,来实际感受下这个神奇算法(看完了很简单,反正我是想不到,嘎嘎)

三:

    code:

public class BitMap {



    /**
     * 创建数组
     */
    public byte[] bits;


    public void consoleBytes(byte b){
        byte[] array = new byte[8];
        for(int i = 7; i >= 0; i--){
            array[i] = (byte)(b & 1);
            b = (byte)(b >> 1);
        }

        for (byte b1 : array) {
            System.out.print(b1);
            System.out.print(" ");
        }

        System.out.println();
    }

    /**

     * 初始化构造执行byte数组扩容
     * @param num
     */
    public  BitMap(int  num){
        bits=new byte[getIndex(num)+1];
        for(int i = 0; i < num; i++){
            add(i);
        }
        int index = 1;
        for(byte bit : bits){
            System.out.println("-------" + index++ + "-------");
            consoleBytes(bit);
        }
    }

    /**
     * 一个byte=8个bit,所以除8,取到num在byte数组的位置
     * @param num
     * @return
     */
    public int getIndex(int num){
        return  num>>3;
    }


    /**
     * num%8得到在byte[index]的位置
     * @param num
     * @return
     */
    public int getPosition(int num){
        return num % 8;
    }

    /**
     * bitmap中添加数据num,标记type中的bit为1,证明存在
     * 将1左移指定位长,然后与当前的byte做| ,则当前位置替换为1
     * @param num
     */
    public  void add(int num){
        int idx=getIndex(num);
        int po=getPosition(num);
        System.out.println(bits[idx]);
        bits[idx]|=1<<po;
    }

    /**
     * 判断指定数字num是否存
     * 将1左移position后,那个位置自然就是1,然后和以前的数据做&,判断是否为0即可
     * @param num
     * @return
     */
    public boolean contains(int num){
        return (bits[getIndex(num)] & 1 << getPosition(num)) != 0;
    }

    /**
     * 重置某一数字对应在bitmap中的值
     * 对1进行左移,然后取反,最后与byte[index]作与操作。
     * @param num
     */
    public void clear( int num){
        bits[getIndex(num)] &= ~(1 << getPosition(num));
    }

    public static void main(String[] args) {
        BitMap bt=new BitMap(100);
        System.out.println(bt.contains(101));
    }
}
 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`Gdiplus::Bitmap::FromStream` 是 GDI+ 库中的一个函数,用于从流中加载图像。其函数原型如下: ```c++ Gdiplus::Status FromStream( IStream *stream, BOOL useEmbeddedColorManagement = FALSE ); ``` 其中,`stream` 参数是一个指向 `IStream` 接口的指针,用于指定要加载的流对象;`useEmbeddedColorManagement` 参数是一个布尔值,用于指定是否使用嵌入的颜色管理数据。 `Gdiplus::Bitmap::FromStream` 函数返回一个 `Gdiplus::Status` 枚举值,表示加载图像的结果。如果加载成功,返回值为 `Gdiplus::Ok`,否则返回其他错误代码。 使用示例: ```c++ Gdiplus::Bitmap* bmp = NULL; // 图像对象指针 IStream* istream = NULL; // 流对象指针 // 创建流对象 CreateStreamOnHGlobal(NULL, TRUE, &istream); // 将数据写入流 // ... // 从流中加载图像 Gdiplus::Status status = Gdiplus::Bitmap::FromStream(istream, &bmp); // 检查是否成功加载图像 if (status != Gdiplus::Ok || bmp == NULL) { // 加载失败,处理错误 // ... } // 成功加载图像,可以使用 bmp 对象进行绘制等操作 // ... // 释放资源 delete bmp; istream->Release(); ``` 在使用 `Gdiplus::Bitmap::FromStream` 函数加载图像时,需要注意以下几点: - 流对象必须在使用完毕后释放,否则会造成内存泄漏; - 图像对象也必须在使用完毕后释放; - 加载图像时需要检查返回值和图像对象是否为空,避免出现错误。 希望这可以帮助到你。如果你有任何问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值