Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 用于在位数组中搜索连续设置/清除位的快速代码?_C++_C_Bitarray_Bitvector - Fatal编程技术网

C++ 用于在位数组中搜索连续设置/清除位的快速代码?

C++ 用于在位数组中搜索连续设置/清除位的快速代码?,c++,c,bitarray,bitvector,C++,C,Bitarray,Bitvector,是否有一些相当快的代码可以帮助我快速搜索大位图(几兆字节)中连续的零位或一位的运行 我所说的“相当快”是指可以利用机器字的大小,一次比较整个字,而不是进行极其缓慢的逐位分析(例如使用vector) 它非常有用,例如,在卷的位图中搜索可用空间(用于碎片整理等)。Windows有一个可以与其API一起使用的数据结构 但是我在前一段时间需要这方面的代码,所以我在这里写了它(警告,它有点难看): 我只对它进行了部分测试,所以它可能仍然有bug(特别是在反向测试时)。但是最近的一个版本(与这个版本略有不

是否有一些相当快的代码可以帮助我快速搜索大位图(几兆字节)中连续的零位或一位的运行

我所说的“相当快”是指可以利用机器字的大小,一次比较整个字,而不是进行极其缓慢的逐位分析(例如使用
vector

它非常有用,例如,在卷的位图中搜索可用空间(用于碎片整理等)。

Windows有一个可以与其API一起使用的数据结构

但是我在前一段时间需要这方面的代码,所以我在这里写了它(警告,它有点难看):

我只对它进行了部分测试,所以它可能仍然有bug(特别是在
反向测试时)。但是最近的一个版本(与这个版本略有不同)似乎对我有用,所以值得一试

整个过程的基本操作是能够快速找到一段位的长度:

long long GetRunLength(
    const void *const pBitmap, unsigned long long nBitmapBits,
    long long startInclusive, long long endExclusive,
    const bool reverse, /*out*/ bool *pBit);
考虑到它的多功能性,其他一切都应该很容易在此基础上构建

我试图包含一些SSE代码,但没有显著提高性能。但是,一般来说,代码比逐位分析快很多倍,因此我认为它可能有用


如果你能在某种程度上掌握<代码> vector < /COD>缓冲区,那么如果你在Visual C++上,那么就可以很容易地测试它了。如果你发现了bug,请随时告诉我。

我不知道如何直接在内存单词上做得很好,所以我制定了一个快速解决方案,就是在字节上工作;为了方便起见,让我们绘制一个计算连续数的算法:

构造两个大小为256的表,其中您将为0到255之间的每个数字写入,即字节开头和结尾的尾随1的数量。例如,对于数字167(二进制为10100111),将1放在第一个表中,将3放在第二个表中。让我们将第一张桌子命名为BBeg,第二张桌子命名为BEnd。然后,对于每个字节b,有两种情况:如果是255,则在当前连续的一组字节的当前和中加上8,即在一个1区域中。否则,用BBeg[b]位结束一个区域,用BEnd[b]位开始一个新区域。 根据您想要的信息,您可以调整此算法(这就是为什么我不在这里放任何代码的原因,我不知道您想要什么输出)

一个缺陷是它不计算一个字节内的(小的)连续的一组


除了这个算法之外,一位朋友告诉我,如果是用于磁盘压缩,只需查找不同于0(空磁盘区域)和255(满磁盘区域)的字节。这是一种快速的启发式方法,可以构建一个映射,以确定要压缩的块。也许这超出了本主题的范围…

听起来这可能很有用:

你不会说你是否想做某种RLE,或者只是简单地计算字节的0和1位(比如0b1001应该返回1x1 2x0 1x1)

查找表加上用于快速检查的SWAR算法可能会很容易地为您提供这些信息。 有点像这样:

byte lut[0x10000] = { /* see below */ };
for (uint * word = words; word < words + bitmapSize; word++) {
   if (word == 0 || word == (uint)-1) // Fast bailout
   {
       // Do what you want if all 0 or all 1
   }
   byte hiVal = lut[*word >> 16], loVal = lut[*word & 0xFFFF];
   // Do what you want with hiVal and loVal
  for (int i = 0; i < sizeof(lut); i++) 
     lut[i] = countContiguousZero(i); // Or countContiguousOne(i)
  // The implementation of countContiguousZero can be slow, you don't care
  // The result of the function should return the largest number of contiguous zero (0 to 15, using the 4 low bits of the byte, and might return the position of the run in the 4 high bits of the byte
  // Since you've already dismissed word = 0, you don't need the 16 contiguous zero case.
字节lut[0x10000]={/*见下文*/};
用于(uint*word=words;word>16],loVal=lut[*word&0xFFFF];
//对hiVal和loVal做你想做的事
LUT必须根据预期的算法进行构造。如果要计算字中连续的0和1的数量,可以这样构造:

byte lut[0x10000] = { /* see below */ };
for (uint * word = words; word < words + bitmapSize; word++) {
   if (word == 0 || word == (uint)-1) // Fast bailout
   {
       // Do what you want if all 0 or all 1
   }
   byte hiVal = lut[*word >> 16], loVal = lut[*word & 0xFFFF];
   // Do what you want with hiVal and loVal
  for (int i = 0; i < sizeof(lut); i++) 
     lut[i] = countContiguousZero(i); // Or countContiguousOne(i)
  // The implementation of countContiguousZero can be slow, you don't care
  // The result of the function should return the largest number of contiguous zero (0 to 15, using the 4 low bits of the byte, and might return the position of the run in the 4 high bits of the byte
  // Since you've already dismissed word = 0, you don't need the 16 contiguous zero case.
for(int i=0;i
难道你不能把你的数组当作一个整数数组,并将整数与零进行比较吗?@Andrew:这取决于你试图实现的目标……这些位可能不会一次对齐8位。你可以比较6个字节(如果bmp是彩色图像文件:6个字节是两个连续的像素)使用6个零的数组。@eharvest:我不是说图片!这与光栅图像完全无关。我是说位数组,即位数组。对不起,我读你的问题太快了。。。