[英]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.