zoukankan      html  css  js  c++  java
  • 毫秒查询9位数qq号码是否存在-BitMap算法应用

    实现详情请查看博客园

    https://www.cnblogs.com/caoke/p/10793885.html

      

    随机注册10万个放入BitMap,然后查询qq号码是否已存在,算法复杂度O(1).

    //BitMap算法demo,查询9位数字
    const b=new BitMap('[0~9][0~9][0~9][0~9][0~9][0~9][0~9][0~9][0~9]')
    
    //设置
    console.time('设置时间')
    for(let i=0;i<b.length;i=i+1000){
        b.set(b.toString(i));
        i=0|Math.random()*1000+i;
    }
    // b.set('123456783')
    // b.set('123456783')
    // b.set('223456783')
    b.set('323456783')
    console.timeEnd('设置时间')
    
    console.time('查询时间')
    console.log(b.has('123456783'))
    console.log(b.has('433456783'))
    console.log(b.has('243456783'))
    console.log(b.has('453456783'))
    console.log(b.has('323456783'))
    console.log(b.has('423456783'))
    console.timeEnd('查询时间')
    

      

    /usr/local/bin/node /Users/caoke/go/bitmap.js
    设置时间: 3212.917ms
    false
    false
    false
    false
    true
    false
    查询时间: 0.629ms

    Process finished with exit code 0

     

    源码

    /*
    *  ckHash函数类,将字符串映射成数字,同时可以将数字映射成字符串,
    *  用于数据压缩,加密解密,以及bitMap大数据查询,去重
    *  作者:caoke
    * */
    
    class ckHash{
        //输入密钥
        constructor(secretKey){
            this.secretKey=secretKey;
    
            this.regexp=new RegExp(secretKey.replace(/[([^[]+?)]/g,function (m) {
                return '('+m.replace(/-/g,'\-').replace(/~/g,'-')+')'
            }).replace(/[\^:.?+]/g,'\$&'));
    
            this.lenArr=[];
            this.dataArr=[];
            secretKey.replace(/[([^[]+?)]/g,(m,p1)=>{
                const arr=[];
                for(let i=0;i<p1.length;i++){
                    if(p1[i]==='~'){
                        arr.push('~')
                    }else{
                        arr.push(p1[i].charCodeAt(0));
                    }
                }
                let length=0;
                for(let i=0;i<arr.length;i++){
                    if(arr[i]==='~'){
                        length=length+arr[i+1]-arr[i-1];
                        i++;
                    }else{
                        length=length+1;
                    }
                }
                this.lenArr.push(length)
                this.dataArr.push(arr)
            })
            this.length=this.lenArr.reduce((x,y)=>x*y)
        }
        //将数字映射成字符串
        toString(number){
            const arr=[];
            for(let i=this.lenArr.length-1;i>0;i--){
                const n1=number%this.lenArr[i];
                arr.unshift(n1)
                number=Math.floor(number/this.lenArr[i]);
            }
            arr.unshift(number)
    
    
            const codeArr=[]
            for(let i=0;i<arr.length;i++){
                const dataArr=this.dataArr[i];
                let len= arr[i];
    
                let code;
                for(let j=0;j<dataArr.length;j++){
                    if(dataArr[j]==='~'){
                        if(len<dataArr[j+1]-dataArr[j-1]){
                            code=dataArr[j-1]+len+1;
                            break;
                        }else{
                            len=len-(dataArr[j+1]-dataArr[j-1]);
                            j++;
                        }
                    }else if(len===0){
                        code=dataArr[j]
                        break;
                    }else{
                        len--;
                    }
                }
                codeArr.push(String.fromCharCode(code))
            }
            let index=0;
            return this.secretKey.replace(/[([^[]+?)]/g,(m,p1)=>{
                return codeArr[index++];
            })
        }
        //将字符串映射成数字
        toNumber(string){
            if(this.regexp.test(string)){
                const arr=[]
                string.replace(this.regexp,function (m,p1) {
                    for(let i=1;i<arguments.length-2;i++){
                        arr.push(arguments[i].charCodeAt(0))
                    }
                });
    
                const lenArr=[]
                for(let i=0;i<arr.length;i++){
                    const dataArr=this.dataArr[i];
                    let len= 0;
                    for(let j=0;j<dataArr.length;j++){
                        if(dataArr[j]===arr[i]){
                            break;
                        }else if(dataArr[j]==='~'){
                            if(arr[i]<=dataArr[j+1]&&arr[i]>dataArr[j-1]){
                                len=len+arr[i]-dataArr[j-1]-1;
                                break;
                            }else{
                                len=len+dataArr[j+1]-dataArr[j-1];
                                j++;
                            }
                        }else{
                            len++;
                        }
                    }
                    lenArr.push(len)
                }
                let number=0;
                let jz=1;
                for(let i=lenArr.length-1;i>=0;i--){
                    number=number+jz*lenArr[i];
                    jz=jz*this.lenArr[i]
                }
    
                return number;
    
            }else{
                throw string +' 不在匹配范围内';
            }
        }
    }
    
    
    //BitMap算法,大数据查询,算法复杂度O(1)
    class BitMap {
        constructor(secretKey){
            this.hashFunc=new ckHash(secretKey);
            this.length=this.hashFunc.length
            this.buffer=Buffer.alloc(this.length);
        }
        has(num){
            if(typeof num ==='string'){
                num=this.toNumber(num);
            }
            const n=num>>3;
            const k=num%8;
            return (this.buffer[n]&1<<k)!==0
        }
        toString(num){
            return this.hashFunc.toString(num);
        }
        toNumber(str){
            return this.hashFunc.toNumber(str);
        }
        set(num){
            if(typeof num ==='string'){
                num=this.toNumber(num);
            }
            const n=num>>3;
            const k=num%8;
            this.buffer[n]=this.buffer[n]|(1<<k);
        }
        del(num){
            if(typeof num ==='string'){
                num=this.toNumber(num);
            }
            const n=num>>3;
            const k=num%8;
            this.buffer[n]=this.buffer[n]&~(1<<k);
        }
    }
    

      

      

  • 相关阅读:
    python学习Day21--内置函数、反射
    python学习Day20--属性、类方法和静态方法+类多继承算法补充
    python学习Day19--面向对象的三大特性
    python学习Day18--继承
    python学习Day17--名称空间
    python学习Day16--面向对象
    python学习Day15--递归与二分查找
    python学习Day14--内置函数
    c# 深克隆与浅克隆
    css test-align 和 margin 居中什么区别
  • 原文地址:https://www.cnblogs.com/caoke/p/10795336.html
Copyright © 2011-2022 走看看