码迷,mamicode.com
首页 > 其他好文 > 详细

统计bytearray中的bitcount

时间:2018-05-25 22:51:15      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:srand   数组   算法   直接   打表   namespace   长度   不能   统计   

给定一个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;
}

统计bytearray中的bitcount

标签:srand   数组   算法   直接   打表   namespace   长度   不能   统计   

原文地址:https://www.cnblogs.com/weiyinfu/p/9090813.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!