6

对于这个数组,尝试这样的事情:

void rollover(int val,int count) {  
    if(count==0) {
        return;
    }
    printf("%d ",val);
    count--;
    rollover(val,count);    
}
int main() {
    int arr[]={0,1};
    for(int i=0;i<=1;i++) {
        rollover(arr[i],4);
    }
    printf("\n");
    return 0;
}

使用递归方法的预期输出:

0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111

无法理解如何编写该 rec 函数。我花了几个小时来解决它。有人可以协助编写该功能吗?

我正在/正在尝试做下面发布的 G_G 之类的事情。我该如何编写这样的递归函数?我必须使用一个 for 循环来调用该递归函数还是使用两个 for 循环进行递归,或者我应该调用递归函数两次?例如:

void rollover(int val,int count) {  
    if(count==0) {
        return;
    }
    printf("%d ",val);
    count--;
    rollover(val,count);
    //.. do something if necessary ..
    rollover(val,count);
    //.. do something if necessary ..
}
4

12 回答 12

27

最简单的解决方案:二进制转换,无递归

for(int i = 0; i < 16: ++i) {
    printf("%u%u%u%u", i/8%2, i/4%2, i/2%2, i%2);  
}

有关此循环的递归版本,请参阅MOHAMED 的答案


以下解决方案使用的二进制递归

          _ 000
   _ 00 _/
  /      \_ 001
 0        _ 010
  \_ 01 _/
         \_ 011
          _ 100
   _ 10 _/
  /      \_ 101
 1        _ 110
  \_ 11 _/
         \_ 111

使用缓冲区的递归解决方案char*,没有二进制转换

void char_buffer_rec(char number[4], int n) {
    if(n > 0) {
        number[4-n] = '0';
        char_buffer_rec(number, n - 1);
        number[4-n] = '1';
        char_buffer_rec(number, n - 1);
    }
    else {
        printf("%s\n", number);
    }
}

用法 :

char number[5] = {0};
char_buffer_rec(number, 4);

仅使用递归解决方案int,无缓冲区,无二进制转换

void int_ten_rec(int number, int tenpower) {
    if(tenpower > 0) {
        int_ten_rec(number, tenpower/10);
        int_ten_rec(number + tenpower, tenpower/10);
    }
    else {
        printf("%04u\n", number);
    }
}

用法 :

int_ten_rec(0, 1000);

该解决方案的另一个版本替换了tenpowerwidth bitwidth,将 printf 替换为width取决于长度变量的可变填充。length可以定义为新参数、程序常量等。

void int_rec(int number, int bitwidth) {
    static int length = bitwidth;
    int i, n;
    if(bitwidth > 0) {
        int_rec(number, bitwidth-1);
        /* n := 10^(bitwidth-2) */
        for(i=0,n=1;i<bitwidth-1;++i,n*=10);
        int_rec(number + n, bitwidth-1);
    }
    else {
        /* i := number of digit in 'number' */
        for(i=1,n=number;n>=10;++i,n/=10);
        /* print (length-i) zeros */
        for(n=i; n<length; ++n) printf("0");
        printf("%u\n", number);
    }
}

用法 :

int_rec(0, 4);

树解决方案,使用char*缓冲区递归,无二进制转换

struct Node {
    int val;
    struct Node *left, *right;
};

void build_tree(struct Node* tree, int n) {
    if(n > 0) {
        tree->left = (Node*)malloc(sizeof(Node));
        tree->right= (Node*)malloc(sizeof(Node));
        tree->left->val = 0;
        build_tree(tree->left, n - 1);
        tree->right->val = 1;
        build_tree(tree->right, n - 1);
    }
    else {
        tree->left = tree->right = NULL;
    }
}

void print_tree(struct Node* tree, char* buffer, int index) {
    if(tree->left != NULL && tree->right != NULL) {
        sprintf(buffer+index, "%u", tree->val);
        print_tree(tree->left, buffer, index+1);
        sprintf(buffer+index, "%u", tree->val);
        print_tree(tree->right, buffer, index+1);
    }
    else {
        printf("%s%u\n", buffer, tree->val);
    }
}

用法 :

    char buffer[5] = {0};
    Node* tree = (Node*)malloc(sizeof(Node));
    tree->val = 0;
    build_tree(tree, 4);
    print_tree(tree, buffer, 0);

但这会0在每行的开头打印一个额外的内容,为避免这种情况,请构建两个较小的树:

    Node* tree0 = (Node*)malloc(sizeof(Node));
    Node* tree1 = (Node*)malloc(sizeof(Node));
    tree0->val = 0;
    tree1->val = 1;
    build_tree(tree0, 3);
    build_tree(tree1, 3);
    print_tree(tree0, buffer, 0);
    print_tree(tree1, buffer, 0);

使用 int* 数组的递归解决方案

#define MAX_LENGTH 32
int number[MAX_LENGTH];
void int_buffer_rec(int n, int length) {
    if(n > 0) {
        number[length - n] = 0;
        int_buffer_rec(n - 1, length);
        number[length - n] = 1;
        int_buffer_rec(n - 1, length);
    }
    else {
        for(int i = 0; i < length; ++i) {
            printf("%u", number[i]);
        }
        printf("\n");
    }
}

用法 :

int_buffer_rec(4, 4);
于 2013-04-22T15:47:23.063 回答
6

递归可以用+1

void f(unsigned int x)
{
   printf("%u%u%u%u\n",
          (x>>3)&0x1,
          (x>>2)&0x1,
          (x>>1)&0x1,
          x&0x1);
   if(x==0xF) return;
   else f(x+1);
}

int main(void)
{
    f(0);
}

执行:

$ ./test
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
于 2013-04-22T15:26:30.407 回答
2

我试图将我的解决方案限制为使用相同的参数,但我肯定会添加一个额外的参数来了解 count 的初始值。

void rec(int val, int count) {
    if (count <= 1) {
        int i;
        int f = 0;
        for (i = sizeof(int) * 8; i >= 0; i--) {
            f |= (val >> i) & 1;
            if (f) {
                printf("%d", (val >> i) & 1);
            }
        }
        printf("\n");
    } else {
        rec(val * 2, count - 1);
        rec(val * 2 + 1, count - 1);
    }
}

输出:

1
10
11
100
101
110
111
1000
1001
1010
1011
1100
1101
1110
1111

为了添加前导 0,我添加了一个参数:

#include <stdio.h>

void rec2(int val, int count, int b) {
    if (count <= 1) {
        int i;
        for (i = b - 1; i >= 0; i--) {
            printf("%d", (val >> i) & 1);
        }
        printf("\n");
    } else {
        rec2(val * 2, count - 1, b);
        rec2(val * 2 + 1, count - 1, b);
    }
}

void rec(int val, int count) {
    rec2(val, count, count);
}

int main() {
    rec(0, 4);
    rec(1, 4);
    return 0;
}

输出:

0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
于 2013-04-25T07:58:23.143 回答
2

只需遍历 DFS 深度为 4 的二叉树,向左为 0,向右为 1。

tr(int dep, int val)
{
   if(dep == 4)
   {
     printf("\n");
   }
   else
   {
     printf("%d", val);
     tr(dep+1, 0); // going left
     tr(dep+1, 1); // going right
   }

   return;
}

int main()
{
   tr(0,0);
}
于 2013-04-22T15:24:37.690 回答
1

让我们从设计递归函数的原型开始。希望从那里开始有意义。查看此代码的非递归版本,您将需要相同的变量。您不需要将它们中的任何一个作为参数传递,但我更愿意将它们全部传递,并使解决方案尽可能灵活和模块化。还要考虑返回值。这可能表明某种成功,以便模仿与 C 标准库的一致性。

int count_r(char *destination, /* The storage for the function to store *
                                *     the 0s and 1s as we count.        */
            size_t length,     /* The number of digits in the number.   */
            char *digit);      /* The set of digits                     */

现在让我们专注于设计第一次迭代。就像在小学一样,我们首先定义我们count_r一次只迭代一个数字。一旦我们可以证明它知道如何从 to 计数09我们就将它引入两位数......但现在,一次一步。

让我们假设在第一次调用之前destination被初始化为包含, 的length字节。digits[0]此初始化由调用者完成,调用者可能会在调用之前输出该预初始化数组。第一次迭代应该只修改一个字节:由 指示的那个length,然后返回给调用者。

int count_r(char *destination, size_t length, char *digit) {
    /* The position of the right-most digit is before the '\0' in destination, *
     *     so we need to decrement length                                      */
    length--;

    /* Find the digit at the very end of destination, within our "digit" parameter */
    char *d = strchr(digit, destination[length]);

    /* d[1] points to the next digit (or '\0') */
    destination[length] = d[1];
    return 0;
}

然后调用者可能会打印数组,并count_r使用相同的缓冲区再次调用以增加计数器。这适用于不同的基数,通过反转digit字符串,我们可以递减而不是递增。但是,正如我们很快就会看到的,它在达到它可以计数的最高数字后失败:'F'在下面的示例中。

int main(void) {
    char num[] = "0";
    do {
        puts(num);
    } while (count_r(num, strlen(num), "0123456789ABCDEF") == 0);
}

当计数更高时,d[1] 将'\0'迭代到超出数字集并进入字符串的空终止符。让我们考虑添加代码来处理我们的第二次迭代。

需要一些代码来设置destination[length]回第digit一个数字并递归地向左移动到下一个数字。这发生在 时d[1] == '\0',因此我们可以编写一个if (...) { ... }分支来处理它。

length传入为0时会出现问题,我们在执行刚才提到的更改后会发现。这是函数应该返回1到的地方,指示计数已经完成,因为它已经尽可能地向左移动并达到了可能的最高数字。

void count_r(char *destination, size_t length, char *digit) {
    /* The position of the right-most digit is before the '\0' in destination, *
     *     so we need to decrement length                                      */
    if (length-- == 0) { return 1; }

    /* Find the digit at the very end of destination, within our "digit" parameter */
    char *d = strchr(digit, destination[length]);

    /* d[1] points to the next digit (or '\0') */
    if (d[1] == '\0') {
        /* Set destination[length] to the first digit */
        destination[length] = digit[0];
        /* Recurse onto the next digit. We've already decremented length */
        return count_r(destination, length, digit);
    }

    destination[length] = d[1];
    return 0;
}

在添加一些assert离子(例如assert(strlen(digit) > 1);)并编写一些测试用例之后,我们可能会决定该函数已准备好用于生产。我希望我能提供帮助。:)

于 2013-04-22T16:29:42.110 回答
1

递归是一种编程技术,它允许程序员根据自己来表达操作。在 C 和 C++ 中,这采用调用自身的函数的形式

#include<iostream>
#include<cstdio>
using namespace std;
void rec(int val)
{
  if(val<16)
  {
    printf("%u%u%u%u", val>>3, (val&4)>>2, (val&2)>>1, val&1);
    printf("\n");
    rec(++val);    //calling val+1 here
  }
  return;
}
int main()
{
   rec(0);  //calling recursion for 0
}

这为您提供了您想要的准确输出..!

如果您不想使用位移运算符..

#include<iostream>
#include<cstdio>
using namespace std;
void rec(int val)
{
   if(val<16)
   {
     for(int b=val,a=8,i=0;i<4;b%=a,a/=2,i++)
     printf("%u",(b/a));
     printf("\n");
     rec(++val);// calling val+1 here
   }
   return;
}

int main()
{
   rec(0);//calling recursion for 0
}
于 2013-04-25T08:53:05.153 回答
1

这个问题可以推广到使用递归来获得任意长度的二进制组合。例如,如果要获取 的所有二进制组合length=4,只需调用printBinaryCombination("????", 0)(即四个?s 需要替换为0or 1)。

对应的代码如下:

void printBinaryCombination(string str, int current)
{
    int length = str.length();
    if (length == 0)
        return;

    if (current == length)
        printf("%s\n", str.c_str());
    else
    {
        if (str[current] == '?')
        {
            str[current] = '0';
            printBinaryCombination(str, current+1);

            str[current] = '1';
            printBinaryCombination(str, current+1);

            // change back for next time
            str[current] = '?';
        }
        else
            printBinaryCombination(str, current+1);
    }
}

编辑:实际上,上面的函数对于处理所有包含随机数?s 的二进制组合也很强大,每个二进制组合都可以是0or 1。例如,如果您调用printBinaryCombination("1??0", 0),它将打印:

1000
1010
1100
1110
于 2013-12-11T04:54:22.883 回答
1

要生成您要求的 n 位组合(您要求 n=4),任何 n 的一般递归实现将是:

主功能:

vector<string> ve,ve1;
int main(int argc, char const *argv[])
{
    /* code */
    int n;
    cin>>n;
    generate("0",n,true);
    generate("1",n,false);
    for(int i=0;i<ve.size();i++){
        cout<<ve[i]<<endl;
    }
    for(int i=0;i<ve1.size();i++){
        cout<<ve1[i]<<endl;
    }
    return 0;
}

生成递归生成二进制字符串的函数:

void generate(string s,int n,bool b){
    if(n==1){
        if(b==true){
            ve.push_back(s);
        }
        else{
            ve1.push_back(s);
        }
        return;
    }else{
        generate(s+"0",n-1,b);
        generate(s+"1",n-1,b);
    }
}

希望这可以帮助..

于 2016-10-21T12:47:29.050 回答
0

SOLN 1:更通用的答案(可在 c90、c99 下编译)。布尔值作为 int 输出。限制:
1)使用数学库。(它更重)。

#include<stdio.h>
#include<math.h>
#define MAXBITS 4
//#define MAXVALUES (((int)pow(2,maxb))-1)
const int MAXVALUES = (((int)pow(2,maxb))-1) //if this gives warning then use #define version.

void bin(int val,int total)
{
    int i = 0;          
    if(val <= MAXVALUES)            //can write pow(2,total-1)-1 but anyways..
    {
        for(i =0 ; i < total;i++)
        {
            printf("%d",!!(val&(int)pow(2,total-i-1)));
        }           
        printf("\n");

    }
    else return;
    bin(val+1,total);
}

int main()
{
    setbuf(stdout,NULL);
    bin(0,MAXBITS);//4 bits 
    return 0;
}

Soln 2:这可以通过字符打印来完成。没有移位运算符。

限制:
1)它只能(正确)打印最多 15(十进制)或 0x0F(十六进制)值。
2)总共
(5 * sizeof(char) * total) + (( total + 2) * (sizeof(int) + sizeof(int)))在堆栈上创建(太浪费了)。

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define MAXVALUES 15
#define MAXBITS 4
void bin(int val,int total) //@prototype void bin(int val);remove redundant total.
{
    char *s = malloc(sizeof(char)*(total+1)); //cant declare variable array(atleast pre c99)
    int i = 0;
    if(val <= MAXVALUES )
    {
        for(i =0 ; i < total;i++)
        {
        s[total - i-1] = !!(val&(int)pow(2,i)) + '0';
        }
        s[total] = '\0';
        printf("%s\n",s);
    }
    else return;
    bin(val+1,total);
}

int main()
{
    bin(0,MAXBITS);//4 bits 
    return 0;
}
于 2013-04-25T08:00:36.093 回答
0

此通用c++代码适用于任意位数。只需将 const int num 更改为您想要生成的二进制代码的任意位数...

const int num=3;
string code="";

void GenerateBinaryCode(string str,unsigned int n){
    if(n==0){
        cout<<str<<endl;
    }
    else{
        str[num-n]='0';
        GenerateBinaryCode(str,  n-1);
        str[num-n]='1';
        GenerateBinaryCode(str, n-1);
    }
}
int main(){
    for(int i=0; i<num; i++)
        code+="x";

    GenerateBinaryCode(code,num);

}
于 2017-04-08T10:25:16.953 回答
0

这是 C 中的递归实现,仅使用 int 2D 数组(无字符串、字符或位移位)用于任意位长度。

static void btable(int* a, int i, int n, int k, size_t len) {
    if (k >= len)
        return;
    for (int j = (i+n)/2; j < n; j++)
        *(a+j*len+k) = 1;
    btable(a,i,(i+n)/2,k+1,len);
    btable(a,(i+n)/2,n,k+1,len);
}

然后你可以调用函数

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

int main(void) {

    int n = 4;
    int (*a)[n] = malloc(sizeof(int[(int)pow(2,n)][n]));
    btable(*a,0,pow(2,n),0,n);

    for (int i = 0; i < pow(2,n); i++) { // verify output
        for (int j = 0; j < n; j++)
            printf("%d",a[i][j]);
        printf("\n");
    }

    return 0;
}
于 2019-01-23T09:29:05.820 回答
-1

在介绍最终解决方案之前,我将展示我们可以用于实现目标的两个函数。

next 函数的主要思想是将l1列表的元素添加到l2. 例如:

l1 = [0]
l2 = [ [1,1] , [1,0] ]
then 
f1(l1,l2) = [ [0,1,1] ,[0,1,0]]


    def f1(l1:List[Int],l2:List[List[Int]]): List[List[Int]] = l2.map{ r=> l1:::r}

第一个参数是一个包含整数列表的列表,该列表将添加到列表中包含的每个数字l2列表中。例如:

l1 = [ [0] , [1]]
l2 = [ [1,0], [1,1] ]
f(l1,l2) = [ [0,1,0],[0,1,1], [1,1,0],[1,1,1] ]


    def f(l1:List[List[Int]],l2:List[List[Int]]): List[List[Int]] = l1.map{ r=> f1(r,l2)} flatten

现在,我们有了辅助方法,我们创建将解决需求的函数

/**
n : The max number of digits that the binary number can contain
*/

    def binaryNumbers(n:Int):List[List[Int]] = n match {
     case 1 => List(List(0),List(1))
     case _ => f( List(List(0),List(1)) , binaryNumbers(n-1) )
    }

Example: binaryNumbers(2) = List( List(0,0), List(0,1), List(1,0), List(1,1) )
于 2017-08-22T00:58:58.553 回答