• bitmap


    1.bitmap可以用来存储用户与标签的对应关系,方便存储与查询
    
    2.查询操作
    
    //查询使用苹果手机的程序员用户
    //程序员用户
    00000001
    //使用苹果手机用户
    00000011
    &
    //得到查询结果
    00000001
    
    //查询男性或00后用户
    //男性用户
    00000011
    |
    //00后用户
    00000100
    //得到结果
    00000111
    
    //查询不是90后的用户
    //90后用户
    00000110
    ^
    //全量用户(包含00,90)
    00001110
    //得到不是90后用户
    00001000
    
    

    bitmap实现原理

    1个int占4字节即4*8=32位,那么我们只需要申请一个int数组长度为 int tmp[1+N/32]即可存储完这些数据,其中N代表要进行查找的总数,tmp中的每个元素在内存在占32位可以对应表示十进制数0~31,所以可得到BitMap表:
    tmp[0]:可表示0~31
    
        tmp[1]:可表示32~63
    
        tmp[2]可表示64~95
    
        .......
        
      如何判断int数字在tmp数组的哪个下标,这个其实可以通过直接除以32取整数部分,例如:整数8除以32取整等于0,那么8就在tmp[0]上。另外,我们如何知道了8在tmp[0]中的32个位中的哪个位,这种情况直接mod上32就ok,又如整数8,在tmp[0]中的第8 mod上32等于8,那么整数8就在tmp[0]中的第八个bit位(从右边数起)。
    
    一个数怎么快速定位它的索引号,也就是说搞清楚byte[index]的index是多少,position是哪一位。举个例子吧,例如add(14)。14已经超出byte[0]的映射范围,在byte[1]范围之类。那么怎么快速定位它的索引呢。如果找到它的索引号,又怎么定位它的位置呢。Index(N)代表N的索引号,Position(N)代表N的所在的位置号。
      Index(N) = N/8 = N >> 3;
      Position(N) = N%8 = N & 0x07;
      
    

    add操作

    
    //得到第几行索引
    let byteIndex = Math.floor(k / 16);
    
    //得到第几列的索引
    let bitIndex = k % 16;
    
    //将1移动到索引的位置并修改该位置
    this.blk[byteIndex] = this.blk[byteIndex] | (1 << bitIndex);
    

    clear操作

      let byteIndex = Math.floor(k / 16);
            let bitIndex = k % 16;
    
    this.blk[byteIndex] &= ~(1 << bitIndex)
    

    contain操作

    !((this.blk[byteIndex] & (1 << bitIndex)) === 0);
    

    完整实现

    
    class BitMap {
        constructor(n) {
            this.nbits = n;
            this.blk = new Array(Math.floor(n / 16) + 1);
            this.blk.fill(0);
        }
    
        get(k) {
            if( k > this.nbits) return false; 
    
            let byteIndex = Math.floor(k / 16);
            let bitIndex = k % 16;
    
            return !((this.blk[byteIndex] & (1 << bitIndex)) === 0);
        }
    
        set(k) {
            if( k > this.nbits) return; 
    
            let byteIndex = Math.floor(k / 16);
            let bitIndex = k % 16;
    
            this.blk[byteIndex] = this.blk[byteIndex] | (1 << bitIndex);
    
        }
    
        clear(k){
            if( k > this.nbits) return; 
    
            let byteIndex = Math.floor(k / 16);
            let bitIndex = k % 16;
    
            return !((this.blk[byteIndex] &= (~(1 << bitIndex))) === 0)
        }
    
    }
    
    let aBitMap = new BitMap(20);
    
    aBitMap.set(1);
    aBitMap.set(3);
    aBitMap.set(5);
    aBitMap.set(7);
    aBitMap.set(9);
    aBitMap.set(11);
    aBitMap.set(13);
    aBitMap.set(15);
    aBitMap.set(17);
    aBitMap.set(19);
    
    console.log(aBitMap.clear(3))
    console.log(aBitMap.get(3))
    console.log(aBitMap.get(1))
    console.log(aBitMap.get(5))
    console.log(aBitMap.get(7))
    console.log(aBitMap.get(9))
    
    // console.log(aBitMap.get(3))
    // for(let i = 0; i < 21; i++) {
    //     console.log(aBitMap.get(i));
    // }
    
  • 相关阅读:
    关于SQL Server系统数据库详解
    如何删除发布服务器distribution
    SQL Server如何删除多余tempDB文件
    SQL Server 中用While循环替代游标Cursor的解决方案
    理解性能的奥秘——应用程序中慢,SSMS中快(4)收集解决参数嗅探问题的信息
    第十六章——处理锁、阻塞和死锁(3)——使用SQLServer Profiler侦测死锁
    第十六章——处理锁、阻塞和死锁(2)——侦测阻塞和阻塞查询
    降级与熔断
    浅淡缓存
    小P的架构生活(下)
  • 原文地址:https://www.cnblogs.com/pluslius/p/11748552.html
Copyright © 2020-2023  润新知