Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C-使用递归打印链表_C_Recursion_Linked List - Fatal编程技术网

C-使用递归打印链表

C-使用递归打印链表,c,recursion,linked-list,C,Recursion,Linked List,我需要用C编写一个函数,给定一个指向链表的指针,该函数将以Python语法输出元素:例如,对于由1,2,3,4和5组成的列表,该函数将输出[1,2,3,4,5] 我已尝试按如下方式编写代码: struct node { struct node *next; int data; }; void print_list(struct node *list) { printf("["); if (list == NULL) { printf(

我需要用C编写一个函数,给定一个指向链表的指针,该函数将以Python语法输出元素:例如,对于由1,2,3,4和5组成的列表,该函数将输出[1,2,3,4,5]

我已尝试按如下方式编写代码:

struct node {
    struct node *next;
    int       data;
};

void print_list(struct node *list) {
    printf("[");
    if (list == NULL) {
        printf("]");
    } else {
        printf("%d", list->data);
        if (list->next != NULL) {
            printf(", ");
        }
        print_list(list->next);
    }
}
输出如下所示:[1、[2、[3、[4、[5[]


我知道每次函数调用自身时,都会打印“[”。是否只有在第一次调用函数时才打印“[”?

您可以创建一个包装函数来打印大括号。在打印之间,调用实际的递归函数,如下所示:

void print_list(struct node *list) {
    putchar('[');
    print_list_helper(list);
    putchar(']');

void print_list_helper(struct node *list) {
    if (list != NULL)
        printf("%d", list->data);
        if (list->next != NULL) {
            printf(", ");
        }
        print_list_helper(list->next);
    }
}

编辑:正如Felix Palmen所说,静态变量是一个选项,但不是最好的。它只在您第一次调用函数时起作用。之后,计数器必须重置,这不容易做到,并且使递归函数不纯

使用
静态
的示例:

#include <stdio.h>

void foo() {
    static int x = 0;
    printf("x In foo: %d\n", x);
    x++;
}

int main() {
    int i;
    for(i = 0; i < 5; i++) {
        foo();
    }

    return 0;
}
void foo() {
    static int x = 0; // initialization (done ONCE!)
    printf("x In foo: %d\n", x);
    x++;
    if(x%2 == 0) x = 0; // reassignment (done as many times as you like)
}
... // everything else is the same
静态整数在函数调用之间保留其值。因此,您可以在第一次调用递归函数时使用它,但每次遇到基本情况时都需要重置它

静态
的另一个示例:

#include <stdio.h>

void foo() {
    static int x = 0;
    printf("x In foo: %d\n", x);
    x++;
}

int main() {
    int i;
    for(i = 0; i < 5; i++) {
        foo();
    }

    return 0;
}
void foo() {
    static int x = 0; // initialization (done ONCE!)
    printf("x In foo: %d\n", x);
    x++;
    if(x%2 == 0) x = 0; // reassignment (done as many times as you like)
}
... // everything else is the same
这使得:

$ ./a.out   
x In foo: 0
x In foo: 1
x In foo: 0
x In foo: 1
x In foo: 0

使用全局变量并将代码更改为

int count=0;
void print_list(struct node *list) {
    if(count==0)
        printf("[");
    if (list == NULL) {
        printf("]");
    } else {
        printf("%d", list->data);
        if (list->next != NULL) {
            printf(", ");
        }
        print_list(list->next);
    }
count++;

}

你可以用一个静态整数

struct node {
    struct node *next;
    int       data;
};

void print_list(struct node *list) {
    static int print_start = 0;
    if (print_start == 0) {
        printf("[");
    }
    if (list == NULL) {
        printf("]");
        print_start = 0;
    } else {
        print_start++;
        printf("%d", list->data);
        if (list->next != NULL) {
            printf(", ");
        }
        print_list(list->next);
    }
}

添加一个额外的参数,显示它是从外部调用还是递归调用。这是最优雅的方法,但会消耗一些堆栈。

在调用递归函数之前打印它怎么样?就像在调用void print_list之前一样?是。第二个选项,在参数中添加一个标志,告诉您是否应该打印一个括号I,但我不会“我不确定我是否被允许这样做,因为这是为了做家庭作业,我认为如果递归不是要求的实际部分(如果这是一个实践作业,可能是这样的话),那么整个过程都应该在函数中打印出来。”,不要这样做递归打印结束括号时还必须将print_start=0设置为好的解决方案。+1如果这是为了练习递归,我认为这不是一个好的解决方案。递归函数的目标通常是纯函数,全局变量无法达到这一目的。另一方面,如果不需要递归,则会有很多h更好的迭代方法。外部else中的if在理论上是无用的。我试图给出一个对原始解修改最少的解。但是,纯解是唯一的解。这个解可以工作,不管它需要是纯的@FelixPalmen。我让它在运行时将计数器重置为零点击链表的末尾,这样它就可以满足OP的需要了。不创建包装函数或全局变量就可以解决问题吗?好主意,但是名称
\u print\u list
很糟糕(因为以下划线开头的标识符是保留的).应该是
print\u list\u content
@M.Ng,是静态整数变量。我不想听起来多余,因为答案已经提出了。@cᴏʟᴅsᴘᴇᴇᴅ 可以重置它,例如在递归调用的尾部。但是,它违背了递归的典型目的,因此我认为您的原始答案确实是最好的。@M.Ng否,在类似于
static int print_start=0;
的情况下,
=0
不是赋值,而是初始化。初始化只会每一次发生一次变量的生存期,无论在何处声明。赋值看起来像
static int print\u start;print\u start=0;
,这确实会在每次调用中赋值。