📜  程序对(大)数组中的设置位数进行计数

📅  最后修改于: 2021-05-25 10:44:57             🧑  作者: Mango

给定一个长度为N的整数数组(任意大数字)。如何计算数组中设置的位数?

一种简单的方法是,创建一种有效的方法来对一个字中的设置位进行计数(最显着的大小,通常等于处理器的位长),然后从数组的各个元素中添加位。

存在多种计数整数的设置位的方法,例如,请参见此方法。这些方法最好运行O(logN),其中N是位数。注意,在处理器N上是固定的,可以在32位计算机上以O(1)时间完成计数,而与总置位位数无关。总的来说,数组中的位可以用O(n)时间计算,其中“ n”是数组大小。

但是,当数组大时,表查找将是更有效的方法。存储可以处理2 32个整数的表查询将是不切实际的。

以下代码说明了一个简单的程序,用于对随机生成的64 K整数数组中的设置位进行计数。想法是生成对前256个数字(一个字节)的查找,并在字节边界处中断数组的每个元素。使用C / C++预处理器的元程序生成查找表,用于对字节中的设置位进行计数。

下表显示了元程序背后的数学推导(添加列和行索引以获取数字,然后查看表以获取该数字中的设置位。例如,要获取10中的设置位,可以是从名为8的行和名为2的列中提取),

0, 1, 2, 3
 0 - 0, 1, 1, 2 -------- GROUP_A(0)
 4 - 1, 2, 2, 3 -------- GROUP_A(1)
 8 - 1, 2, 2, 3 -------- GROUP_A(1)
12 - 2, 3, 3, 4 -------- GROUP_A(2)
16 - 1, 2, 2, 3 -------- GROUP_A(1)
20 - 2, 3, 3, 4 -------- GROUP_A(2)
24 - 2, 3, 3, 4 -------- GROUP_A(2)
28 - 3, 4, 4, 5 -------- GROUP_A(3) ... so on

从表中,在表以及组参数中都有一个以4的倍数出现的模式。序列可以如代码中所示一般化。

复杂:

除了遍历数组之外,所有操作都需要O(1)。时间复杂度为O(n),其中“ n”是数组的大小。空间复杂度取决于生成查询的元程序。

代码:

C++
#include 
#include  
using namespace std; 
  
  
/* Size of array 64 K */
#define SIZE (1 << 16) 
  
/* Meta program that generates set bit count 
array of first 256 integers */
  
/* GROUP_A - When combined with META_LOOK_UP 
generates count for 4x4 elements */
  
#define GROUP_A(x) x, x + 1, x + 1, x + 2 
  
/* GROUP_B - When combined with META_LOOK_UP 
generates count for 4x4x4 elements */
  
#define GROUP_B(x) GROUP_A(x), GROUP_A(x+1), GROUP_A(x+1), GROUP_A(x+2) 
  
/* GROUP_C - When combined with META_LOOK_UP 
generates count for 4x4x4x4 elements */
  
#define GROUP_C(x) GROUP_B(x), GROUP_B(x+1), GROUP_B(x+1), GROUP_B(x+2) 
  
/* Provide appropriate letter to generate the table */
  
#define META_LOOK_UP(PARAMETER)\ 
GROUP_##PARAMETER(0),\ 
GROUP_##PARAMETER(1),\ 
GROUP_##PARAMETER(1),\ 
GROUP_##PARAMETER(2)\ 
  
int countSetBits(int array[], size_t array_size) 
{ 
int count = 0; 
  
/* META_LOOK_UP(C) - generates a table of 256 integers whose 
    sequence will be number of bits in i-th position 
    where 0 <= i < 256 
*/
  
    /* A static table will be much faster to access */
    static unsigned char const look_up[] = { META_LOOK_UP(C) }; 
  
    /* No shifting funda (for better readability) */
    unsigned char *pData = NULL; 
  
for(size_t index = 0; index < array_size; index++) 
{ 
    /* It is fine, bypass the type system */
    pData = (unsigned char *)&array[index]; 
  
    /* Count set bits in individual bytes */
    count += look_up[pData[0]]; 
    count += look_up[pData[1]]; 
    count += look_up[pData[2]]; 
    count += look_up[pData[3]]; 
} 
  
return count; 
} 
  
/* Driver program, generates table of random 64 K numbers */
int main() 
{ 
int index; 
int random[SIZE]; 
  
/* Seed to the random-number generator */
srand((unsigned)time(0)); 
  
/* Generate random numbers. */
for( index = 0; index < SIZE; index++ ) 
{ 
    random[index] = rand(); 
} 
  
cout << "Total number of bits = "<< countSetBits(random, SIZE); 
return 0; 
} 
  
// This is code is contributed by rathbhupendra


C
#include 
#include 
#include 
  
/* Size of array 64 K */
#define SIZE (1 << 16)
  
/* Meta program that generates set bit count
   array of first 256 integers */
  
/* GROUP_A - When combined with META_LOOK_UP
   generates count for 4x4 elements */
  
#define GROUP_A(x) x, x + 1, x + 1, x + 2
  
/* GROUP_B - When combined with META_LOOK_UP
   generates count for 4x4x4 elements */
  
#define GROUP_B(x) GROUP_A(x), GROUP_A(x+1), GROUP_A(x+1), GROUP_A(x+2)
  
/* GROUP_C - When combined with META_LOOK_UP
   generates count for 4x4x4x4 elements */
  
#define GROUP_C(x) GROUP_B(x), GROUP_B(x+1), GROUP_B(x+1), GROUP_B(x+2)
  
/* Provide appropriate letter to generate the table */
  
#define META_LOOK_UP(PARAMETER) \
   GROUP_##PARAMETER(0),  \
   GROUP_##PARAMETER(1),  \
   GROUP_##PARAMETER(1),  \
   GROUP_##PARAMETER(2)   \
  
int countSetBits(int array[], size_t array_size)
{
   int count = 0;
  
   /* META_LOOK_UP(C) - generates a table of 256 integers whose
      sequence will be number of bits in i-th position
      where 0 <= i < 256
   */
  
    /* A static table will be much faster to access */
       static unsigned char const look_up[] = { META_LOOK_UP(C) };
  
    /* No shifting funda (for better readability) */
    unsigned char *pData = NULL;
  
   for(size_t index = 0; index < array_size; index++)
   {
      /* It is fine, bypass the type system */
      pData = (unsigned char *)&array[index];
  
      /* Count set bits in individual bytes */
      count += look_up[pData[0]];
      count += look_up[pData[1]];
      count += look_up[pData[2]];
      count += look_up[pData[3]];
   }
  
   return count;
}
  
/* Driver program, generates table of random 64 K numbers */
int main()
{
   int index;
   int random[SIZE];
  
   /* Seed to the random-number generator */
   srand((unsigned)time(0));
  
   /* Generate random numbers. */
   for( index = 0; index < SIZE; index++ )
   {
      random[index] = rand();
   }
  
   printf("Total number of bits = %d\n", countSetBits(random, SIZE));
   return 0;
}