简体   繁体   English

用二进制数填充数组

[英]Fill array with binary numbers

First of all this is not homework! 首先这不是功课!

My question is from the book: Algorithms in C++ third edition by Robert Sedgewick. 我的问题来自 Robert Sedgewick所著的《 C ++算法》第三版

There is given an array of size n by 2^n (two dimensional) and we should fill it with binary numbers of bits size exactly n. 给定大小为n乘2 ^ n(二维)的数组,我们应该用二进制数正好为n的位数填充它。 For example for n=5 the result will be: 例如对于n = 5,结果将是:

00001
00010
00011
00100
00101
00110
00111    

And so on. 等等。 We should put this sequence of bits into arrays. 我们应该将此位序列放入数组中。

I do not know much C/C++, but a naïve, language-agnostic approach would be to simply find a formula for A[i, j], where i \\in [0, 2^n - 1] and j \\in [0, n-1]. 我不太了解C / C ++,但是一种幼稚的,与语言无关的方法将是简单地找到A [i,j]的公式,其中i \\ in [0,2 ^ n-1]和j \\ in [ 0,n-1]。

In words, A[i, j] contains the jth binary digit of i, counting from the most significant bit. 换句话说,A [i,j]包含i的第j个二进制数,从最高有效位开始计数。

In formulae, A[i, j] = (i AND 2^(n-1-j) ) SHR (n-1-j) 在公式中,A [i,j] =(i AND 2 ^(n-1-j))SHR(n-1-j)

where AND is the binary bitwise and operator, and SHR is the binary "shift bits right" operator. 其中AND是二进制按位与运算符,而SHR是二进制“右移位”运算符。 a^b means (of course) "a raised to the power of b". a ^ b的意思是(当然)“ a提升为b的幂”。

Ugly Proof-Of-Concept Delphi Code: 丑陋的概念验证Delphi代码:

var
  i: Integer;
  twoton: integer;
  j: Integer;
begin
  twoton := round(IntPower(2, n));
  SetLength(A, twoton, n);
  for i := 0 to twoton - 1 do
    for j := 0 to n - 1 do
      A[i, j] := (i and round(IntPower(2, n-1-j))) shr (n-1-j);

This works perfectly, but I am quite sure there are faster ways... At least one could store the powers of 2 in an array and use POWEROF2[k] rather than round(IntPower(2, k)), but - of course - this depends on your language. 这可以正常工作,但是我很确定有更快的方法……至少一个可以将2的幂存储在数组中,并使用POWEROF2 [k]而不是round(IntPower(2,k)),但是-当然-这取决于您的语言。 After all, IntPower is a Delphi function. 毕竟,IntPower是Delphi函数。

How this works 如何运作

Say that we have the number 23, or, in binary 10111. Now we want the third binary digit. 假设我们有数字23,或二进制10111。现在我们要第三个二进制数字。 Then we want to AND the number 10111 with the number 00100, to obtain 00100 if the sought digit is one, and 00000 otherwise. 然后,我们要对10111和00100进行“与”运算,如果要查找的数字为1,则为00100,否则为00000。 Notice that 00100, the number we AND with, is simply 2^3 in decimal; 请注意,与我们进行运算的数字00100只是十进制2 ^ 3; hence all powers-of-2. 因此所有2的幂。 Now we have the number 00N00, where N is the sought digit, in this example 1: 00100. We now shift the bits of this number 3 steps to the right (the SHR operation), to obtain 00001 = 1, and - voilà! 现在我们有了数字00N00,其中N是要查找的数字,在本例中为1:00100。我们现在将该数字的位向右移动3步(SHR操作),以获得00001 = 1,并且-voilà! - we have gotten our digit! -我们已经掌握了数字!

A Smarter Approach 更聪明的方法

I do not know how C stores arrays, but you could simply create a 2^N-dimensional vector A of unsigned integers (8-bit, 16-bit, or 32-bit, preferably), namely the numbers 0, 1, 2, ..., 2^N - 1, and then argue that this actually is a two-dimensional matrix . 我不知道C如何存储数组,但是您可以简单地创建一个2 ^ N维向量 A,该向量 A是无符号整数(最好是8位,16位或32位),即数字0、1、2 ,...,2 ^ N-1,然后认为这实际上一个二维矩阵 Indeed, if we introduce the notation UNSINGED_INTEGER[k] as the kth bit of UNSIGNED_INTEGER, then A[i][k] is more or less the matrix you wanted... 确实,如果我们将符号UNSINGED_INTEGER [k]引入UNSIGNED_INTEGER的第k位,则A [i] [k]或多或少是您想要的矩阵...

Each number is one more than the last in the binary number system. 每个数字都比二进制数字系统中的最后一个数字大一个。

To increment (add one) in binary 以二进制递增(加一)

  • start at the right end of the number 从数字的右端开始
  • turn all trailing ones, if any, into zeroes 将所有尾随的(如果有的话)都归零
  • turn the last 0 into a 1 将最后一个0变成1
  • if there isn't a 0 in the string, you've gone too far. 如果字符串中没有0,则说明您做得太过分了。

Note that the << operator multiplies the left operand by two to the power of the right operand. 请注意, <<操作符将左侧操作数乘以2等于右侧操作数的幂。 The number 1l is simply 1 expressed as a long , which is 64 bits on a 64-bit system. 数字1l简单地用1表示为long ,在64位系统上为64位。

template< size_t n > // template detects size of array. Strictly optional.
void ascending_binary_fill( bool (&arr)[ 1l << n ][ n ] ) {
    std::fill( arr[0], arr[0] + n, 0 ); // first # is 0
    for ( size_t pred = 0; pred < 1l << n; ++ pred ) {
        int bit = n; // pred = index of preceding number; bit = bit index
        while ( arr[ pred ][ -- bit ] ) { // trailing 1's in preceding #
            arr[ pred+1 ][ bit ] = 0; // ... are trailing 0's in current #
        }
        arr[ pred+1 ][ bit ] = 1;
        std::copy( arr[ pred ], arr[ pred ] + bit, arr[ pred+1 ] );
    }
}

Quite simple! 非常简单!

here is a solution in pseudocode 这是伪代码的解决方案

assert(bits <= 32)
int array[pow(2, bits)] 
for (uint i= 0; i < length(array); i++)
    array[i]= i;

The result is an array filled with the pattern you gave as an example 结果是一个数组,其中填充了您作为示例给出的模式

public static uint[][] FillUpCode(uint qValue, uint kValue)
    {
        var size = (ulong)Math.Pow(qValue, kValue);
        var array = new uint[size][];

        var workArray = new uint[kValue];
        long position = kValue - 1;
        ulong n = 0;

        while (position > 0)
        {
            while (workArray[position] < qValue)
            {
                var tempArray = new uint[kValue];
                Array.Copy(workArray, tempArray, kValue);
                array[n++] = tempArray;
                workArray[position]++;
            }

            while (position > 0)
            {
                workArray[position] = 0;
                if (workArray[position - 1] < (qValue - 1))
                {
                    workArray[position - 1]++;
                    position = kValue - 1;
                    break;
                }
                position--;
            }
        }
        return array;
    }


qValue - number base, kValue - line length :) Code may be useful when you need to generate array in different number basis. qValue-数字基,kValue-行长:)当您需要以其他数字基生成数组时,代码可能会很有用。

// My solution is based on that of Potatoswatter.

// use cols value where rows = 2^cols
// start here after setting cols
rows = pow(2.0, double(cols));

// memory allocation
bool **array = new bool*[rows];
for (int i = 0; i < rows; i++) {
    array[i] = new bool[cols];
}

std::fill( array[0], array[0] + cols, 0 ); // maybe not needed

for (int i = 1; i < rows; i++) { // first row is zero, start at second 
    // starting at right ...
    int j = lits - 1;
    // turn the last zero into a one
    if (array[i][j] == false) {
        array[i][j] = true;
    }
    else {
        // turn all trailing ones into zeros (prior to first zero)
        while (array[i][j] == true) {
            array[i][j] = false;
            j--;
        }
        array[i][j] = true;
    }
    // copy this row to next row
    if (i < (rows - 1)) {
        std::copy(array[i], array[i] + lits, array[i+1]);
    }
}

So basically, you need an array that starts at zero, and goes up to 2^n? 因此,基本上,您需要一个从零开始到2 ^ n的数组?
Psuedo-C: 伪C:

 bool[][] Fill(int n) { max = Pow(2, n); array = new bool[max, n]; for i from 0 to max - 1 for j from 0 to n - 1 array[i][n - j - 1] = ((i >> j) & 1) == 1; return array; } 

The only problem I can see with that is that it capped at n = 32, but that will already take enormous amounts of memory so that really is a non-issue. 我可以看到的唯一问题是它的上限为n = 32,但这已经占用了大量内存,因此实​​际上不是问题。
Note that you could as well make it a one dimensional number and fill it with numbers from 0 to 2^n, and the A[i][j]th element will actually be retrieved using (A[i]>>j) & 1. 请注意,您也可以将其设为一维数,并用0到2 ^ n的数字填充,实际上将使用(A [i] >> j)&检索第A [i] [j]个元素1。

This is a very rudimentary problem, and I will demonstrate with this Java snippet: 这是一个非常基本的问题,我将通过以下Java代码片段进行演示:

public class Bin {                                                  // prints:   
   static String zero(int L) {                                      // 0000
      return (L <= 0 ? "" : String.format("%0" + L + "d", 0));      // 0001
   }                                                                // 0010
   static String zeroPad(String s, int L) {                         // 0011
      return zero(L - s.length()) + s;                              // 0100
   }                                                                // 0101
   public static void main(String[] args) {                         // 0110
      final int N = 4;                                              // 0111
      for (int i = 0; i < (1 << N); i++) {                          // 1000
         System.out.println(zeroPad(Integer.toBinaryString(i), N)); // 1001
      }                                                             // 1010
   }                                                                // 1011
}                                                                   // 1100
                                                                    // 1101
                                                                    // 1110
                                                                    // 1111

I will leave it to you to figure out how to implement toBinaryString and how to populate int[][] with the bits. 我将留给您了解如何实现toBinaryString以及如何使用这些位填充int[][]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 用二进制数填充矩阵,常规和格雷编码 - Fill matrix with binary numbers, regular and gray coded int数组:填充从一到给定数字的所有数字组合 - int array: fill with all combinations of numbers from one to a give number 在最小数量的比较中二进制搜索大数组中的多个不同数字 - Binary search for multiple distinct numbers in a large array in minimum number of comparisons 如何使用二进制搜索计算排序数组中唯一数字的数量? - How to count the number of unique numbers in sorted array using Binary Search? 报告整数数组中所有缺失的数字(以二进制表示) - Report all missing numbers in an array of integers (represented in binary) 删除偶/奇数以找到二进制表示的数字数组中的缺失数字 - Removing even/odd numbers to find missing number in an array of array of numbers represented in binary 二进制到十进制(大数) - Binary to decimal (on huge numbers) Java中的二进制数相加 - Adding binary numbers in Java 用2个不同的数字填充2D数组,但是每个数字都必须放在等号旁边 - Fill 2D array with 2 different numbers, but each number has to be placed next to an equal number 使用复杂度为O(n)的唯一随机数填充大小为n的Java数组 - fill an array in Java of size n with unique random numbers with complexity O(n)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM