zoukankan      html  css  js  c++  java
  • 统计bytearray中的bitcount

    给定一个byte数组,要求统计byte数组的bitcount,也就是byte数组中为1的位的个数。

    Redis提供了位数组数据结构,位数组是相对独立的一个程序,在《Redis设计与实现》(黄建宏著)一书中,对此有详细介绍。

    回到问题上来,看到这个问题的第一印象就是暴力。假设byte数组长度为n,那么时间复杂度为8n。
    我们的目的就是优化常数。

    很容易想到的是用空间换时间,预先打表0~255之间的全部数字的bitcount,用到时直接查表,复杂度将为O(n).
    这种方法的缺点在于只能存储8位而不能存储太多,因为随着位数的增加,空间消耗指数级增长。

    最高级的一种优化方法建立在位运算基础上。这种方法的思想基于分治算法。
    首先两两一组分成16组,然后四四一组分成8组,八八一组分成4组,16、16一组分成两组。
    统计各个组内1的个数,然后归并可以通过移位运算和加法运算实现。

    #include<iostream>
    #include<stdlib.h>
    #include<time.h>
    using namespace std;
    int bitcountBruteForce(char*a,int len){
        int s=0;
        for(int i=0;i<len;i++){
            for(int j=0;j<8;j++){
                if(a[i]&(1<<j)){
                    s++;
                }
            }
        }
        return s;
    }
    int table[1<<8];
    int bitcountTable(char*a,int len){
        int s=0;
        for(int i=0;i<len;i++){ 
            s+=table[int(a[i]&0xff)];
        }
        return s;
    }
    int swar(int x){
        x=(x&0x55555555)+((x>>1)&0x55555555);
        x=(x&0x33333333)+((x>>2)&0x33333333);
        x=(x&0x0f0f0f0f)+((x>>4)&0x0f0f0f0f);
        x=(x*0x01010101)>>24;
        return x;
    }
    int swar2(int x){
        x=(x&0x55555555)+((x>>1)&0x55555555);
        x=(x&0x33333333)+((x>>2)&0x33333333);
        x=(x&0x0f0f0f0f)+((x>>4)&0x0f0f0f0f);
        x=(x&0x00ff00ff)+((x>>8)&0x00ff00ff);
        x=(x&0x0000ffff)+((x>>16)&0x0000ffff);//x=(x>>16)+(x&31);
        return x;
    }
    int bitcountSWAR(char*a,int len){
        int s=0;
        int intLen=len/4;
        int left=len%4;
        int*ia=(int*)a;
        for(int i=0;i<intLen;i++){
            s+=swar2(*ia);
            ia++;
        }
        for(int i=intLen*4;i<len;i++){
            s+=table[a[i]];
        }
        return s;
    }
    void initTable(){
        for(int i=0;i<(1<<8);i++){
            int s=0;
            for(int j=0;j<8;j++){
                if(i&(1<<j)){
                    s++;
                }
            }
            table[i]=s;
        }
    }
    int timeit(int(*f)(char*,int),char*a,int len,int manytimes){
        int begtime=time(0);
        int res=0;
        for(int i=0;i<manytimes;i++){
            res=f(a,len);
        }
        cout<<"ans "<<res<<endl;
        int endtime=time(0);
        int timeused=endtime-begtime;
        return timeused;
    }
    int main(){
        const int n=1e6;
        int a[n];
        initTable();
        srand(time(0));
        for(int i=0;i<n;i++){
            a[i]=rand();
        }
        cout<<"brute force "<<timeit(bitcountBruteForce,(char*)a,n*sizeof(int),10)<<endl;
        cout<<"table method "<<timeit(bitcountTable,(char*)a,n*sizeof(int),10)<<endl;
        cout<<"swar method "<<timeit(bitcountSWAR,(char*)a,n*sizeof(int),10)<<endl;
        return 0;
    }
    
  • 相关阅读:
    TensorFlow 使用预训练好的卷积神经网络和循环神经网络(lstm)模型处理图片转文字(im2txt)
    45度做人,90度做事,180度为人,360度处事
    SQL Server 和 Oracle 数据类型对应关系
    SQL Server 创建数据库
    SQL Server 2012 忘记sa用户处理方法
    剑指offer50:数组中重复的数字
    剑指offer49:把字符串转换成整数
    剑指offer48:不用加减乘除做加法
    剑指offer47:位运算+递归。求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
    剑指offer46:圆圈中最后剩下的数字(链表,递归)
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/9090813.html
Copyright © 2011-2022 走看看