簡體   English   中英

獲取 BitMap 中設置的位列表

[英]Get list of bits set in BitMap

在 C 中,是否有任何優化的方法可以在不解析每個位的情況下檢索 BitPositions 集列表。

考慮以下示例

int bitmap[4];

所以,有 4 * 32 位位置..值如下

bitmap = { 0x1, 0x0, 0x0, 0x0010001 }

我想檢索每個位集的位置,而不是從 0 到 4 * 32 個位置進行解析。

首先,在 C 中不能真正將int用於位圖,因為將一位左移到符號位具有未定義的行為,C 不保證表示是二進制補碼,或者 int 中有 32 位; 據說避免這些陷阱的最簡單方法是使用<stdint.h>uint32_t代替。 因此

#include <stdint.h>
uint32_t bitmap[4];

因此,請考慮將這些位從索引 0 ... 3 編號為 0 ... 127; 並且在索引 0 ... 31 內; 因此,您可以使用以下公式獲取數組中的索引和該值中的位數:

int bit_number = // a value from 0 ... 127
int index = value >> 32; // shift right by number of bits in each index
int bit_in_value = value & 31; // take modulo 32 to get the bit in value

現在您可以通過以下方式索引整數:

bitmap[index];

並且所需值的位掩碼是

uint32_t mask = (uint32_t)1 << bit_in_value;

這樣您就可以檢查該位是否已通過執行

bit_is_set = !!(bitmap[index] & mask);

現在為了加快速度,您可以跳過bitmap[index]為 0 的任何index ,因為它不包含任何位集; 同樣,在每個索引中,您可以通過將位圖中 uint32_t 中的位右移1 並用 1 屏蔽來加快速度; 並在 uint32_t 變為 0 時中斷循環:

for (int index = 0; index <= 3; index ++) {
     uint32_t entry = bitmap[index];
     if (! entry) {
         continue;
     }

     int bit_number = 32 * index;
     while (entry) {
         if (entry & 1) {
             printf("bit number %d is set\n", bit_number);
         }
         entry >>= 1;
         bit_number ++;
     }   
}

除此之外,除了查找表或使用編譯器內在函數之外,沒有什么可以加速的,例如設置哪個是最低位集,但無論如何您仍然必須使用一些。

在 O(k) 中運行的最佳解決方案,其中 k = 整個列表中設置位的總數,可以通過使用查找表來實現。 例如,您可以使用一個包含 256 個條目的表來描述該字節中每個設置位的位位置。 索引將是字節的實際值。

對於每個條目,您可以使用以下結構。

struct
{
   int numberOfSetBits;
   char* list; // use malloc and alloocate the list according to numberOfSetBits
}

然后,您可以遍歷每個結構的列表成員,迭代次數 = 該字節的設置位數。 對於 32 位整數,您必須遍歷其中的 4 個結構,每個字節一個。 要確定您需要檢查哪個條目,請使用位圖並移位 8 位。 請注意,位位置與該字節相關,因此您可能需要添加偏移量或 24、16 或 8,具體取決於您迭代的字節(假設為 32 位整數)。

注意:如果額外的內存使用對您來說不是問題,您可以構建一個 64K 的 16 位條目表,您將結構的數量減少一半。

與此問題相關,您可以看到返回 64 位整數中所有設置位位置的最快方法是什么?

一個簡單的解決方案,但可能不是最快的,這取決於 log 和 pow 函數的時間:

#include<math.h>
#include<stdio.h>

void getSetBits(unsigned int num, int offset){

    int bit;
    while(num){
        bit = log2(num);
        num -= pow(2, bit);

        printf("%i\n", offset + bit); // use bit number
    }
}

int main(){
    int i, bitmap[4] = {0x1, 0x0, 0x0, 0x0010001};
    for(i = 0; i < 4; i++)
        getSetBits(bitmap[i], i * 32);
}

復雜度 O(D) | D 是設置位數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM