Algorithm 迭代一个位序列并查找每个集合位

Algorithm 迭代一个位序列并查找每个集合位,algorithm,bit-manipulation,Algorithm,Bit Manipulation,我的问题或多或少是标题里有什么;我想知道是否有一种快速的方法来遍历一系列位并找到每一个已设置的位 更详细的资料: 我目前正在研究表示一组对象的数据结构。为了支持我需要的一些操作,结构必须能够在内部执行子集的快速交集。我提出的解决方案是用“位数组”表示结构超集的每个子集,其中每个位映射到数组中保存超集数据的索引。示例:如果在子集中设置了位#1,则超集数组中索引1处的元素在子集中存在 每个子集由一个ulong数组组成,该数组足够大,有足够的位表示整个超集(如果超集包含256个元素,则数组的大小必须为

我的问题或多或少是标题里有什么;我想知道是否有一种快速的方法来遍历一系列位并找到每一个已设置的位

更详细的资料:

我目前正在研究表示一组对象的数据结构。为了支持我需要的一些操作,结构必须能够在内部执行子集的快速交集。我提出的解决方案是用“位数组”表示结构超集的每个子集,其中每个位映射到数组中保存超集数据的索引。示例:如果在子集中设置了位#1,则超集数组中索引1处的元素在子集中存在

每个子集由一个ulong数组组成,该数组足够大,有足够的位表示整个超集(如果超集包含256个元素,则数组的大小必须为256/64=4)。为了找到两个子集S1和S2的交集,我可以简单地遍历S1和S2的数组,并在每个索引处的ulong之间找到按位and

现在回到我的问题的实质: 为了返回子集的数据,我必须遍历子集“位数组”中的所有位,并找到设置的位。我现在就是这样做的:

 /// <summary>
 /// Gets an enumerator that enables enumeration over the strings in the subset.
 /// </summary>
 /// <returns> An enumerator. </returns>
 public IEnumerator<string> GetEnumerator()
 {
     int bitArrayChunkIndex = 0; 
     int bitArrayChunkOffset = 0; 
     int bitArrayChunkCount = this.bitArray.Length; 

     while(bitArrayChunkIndex < bitArrayChunkCount)
     {
         ulong bitChunk = bitArray[bitArrayChunkIndex];

         // RELEVANT PART

         if (bitChunk != 0)
         {
              int bit = 0;
              while (bit < BIT_ARRAY_CHUNK_SIZE  /* 64 */)
              {
                   if(bitChunk.BitIsSet(bit))
                        yield return supersetData[bitArrayChunkOffset + bit];
                   bit++;
              }
         }
         bitArrayChunkIndex++;
         bitArrayChunkOffset += BIT_ARRAY_CHUNK_SIZE;

         // END OF RELEVANT PART
     }
 }
//
///获取一个枚举数,该枚举数对子集中的字符串启用枚举。
/// 
///统计员。
公共IEnumerator GetEnumerator()
{
int bitArrayChunkIndex=0;
int bitArrayChunkOffset=0;
int bitArrayChunkCount=this.bitArray.Length;
while(bitArrayChunkIndex

有什么明显的方法可以优化这一点吗?有没有什么小技巧可以让它做得很快?谢谢

取一个十六个整数的数组,用为整数设置的位数从零到十五(即0、1、1、2、1、2、3、1、2、2、3、2、3、3、3、3、4)初始化。现在获取bitchunk%16,并在int数组中查找结果-这是块的前四位中的设置位数。右移四次,然后再重复整个操作十五次

您可以使用256个整数的数组和8位子块来代替。我不建议使用带有12位子块的4096个整数数组,这有点荒谬

int[] lookup = new int[16] {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
int bitCount = 0;
for(int i = 0; i < 16; i++) {
    int firstFourBits = bitChunk % 16;
    bitCount += lookup[firstFourBits];
    bitChunk = butChunk >> 4;
}
int[]lookup=newint[16]{0,1,1,2,2,1,2,3,1,2,2,3,2,3,3,3,3,4};
int位计数=0;
对于(int i=0;i<16;i++){
int firstFourBits=位块%16;
bitCount+=查找[firstFourBits];
bitChunk=butChunk>>4;
}

在英特尔386+上,可以先使用机器指令位搜索。 下面是gcc的示例。这对于处理64位字来说有点棘手, 但无论如何,它工作起来又快又有效

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main(int argc, char **argv) {
  uint64_t val;
  sscanf(argv[1], "%llx", &val);
  printf("val=0x%llx\n", val);
  uint32_t result;
  if((uint32_t)val) { // first bit is inside lowest 32
    asm("bsfl %1,%0" : "=r"(result) : "r"(val));
  } else {             // first bit is outside lowest 32
    asm("bsfl %1,%0" : "=r"(result) : "r"(val >> 32));
    result += 32;
  }
  printf("val=%llu; result=%u\n", val, result);
  return 0;
}
#包括
#包括
#包括
int main(int argc,字符**argv){
uint64_t val;
sscanf(argv[1]、“%llx”、&val);
printf(“val=0x%llx\n”,val);
uint32_t结果;
如果((uint32_t)val){//第一位在最低32位之内
asm(“bsfl%1,%0”:“=r”(结果):“r”(val));
}否则{//第一位在最低32位之外
asm(“bsfl%1,%0”:“=r”(结果):“r”(val>>32));
结果+=32;
}
printf(“val=%llu;result=%u\n”,val,result);
返回0;
}

此外,在使用x64体系结构时,您可以尝试使用bsfq指令,并删除“if/else”

您可能可以从这里使用一些东西:它的应用程序是什么?它取决于您何时需要数据您可以在不同的时间获取数据。这个问题有许多技术可以适应您的内部循环。我自己使用bsf/bsr。有一个位数组类: