C-使用递归打印链表
我需要用C编写一个函数,给定一个指向链表的指针,该函数将以Python语法输出元素:例如,对于由1,2,3,4和5组成的列表,该函数将输出[1,2,3,4,5] 我已尝试按如下方式编写代码: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(
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;
,这确实会在每次调用中赋值。