这里是C的初学者,试图了解有关链接列表的更多信息。
下面的代码应该从称为“士兵”的结构创建一个循环的双向链表。 int n
很重要,因为它确定了创建的节点数,每个节点都包含一个int data
,且值为n
的{{1}}。
因此,当用户输入n=>1
时,链接列表将如下所示:
n=6
我已经在这里停留了一段时间。我正在尝试查看丢失的内容,但看不到。一切都会编译文件,除了我只会得到以下错误: [Error]预期在'*'标记之前的'=',',',';','asm'或'__attribute __' >
6 <-> 5 <-> 4 <-> 3 <-> 2 <-> 1
^ ^
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
答案 0 :(得分:1)
我发现了一些潜在的问题:
您的create_soldier
原型具有两种返回类型:
void soldier* create_soldier (int sequence){ ... }
您必须选择一个!我在函数中没有看到return
,因此它可能应该是目前的void
函数:
void create_soldier (int sequence){ ... }
您正在此处比较int
和NULL
:
if(head->data==NULL)
NULL
只能与指针进行有意义的比较,因此您可能打算比较指向士兵head
而不是其data
成员的指针:
if (head == NULL)
void display(soldier* head)
被定义了两次,因此您需要删除或重命名一个定义。它们看起来与我相同,所以我认为您可以删除一个。
最后,别忘了free
用完malloc
后分配给您的内存。如果不这样做,最终将导致内存泄漏。对于一个小的程序来说可能并不重要,但是这是一个提早开始的好习惯。
答案 1 :(得分:1)
有一些错误。返回类型不正确,数据初始化会发出警告,因为您正在将指针与int进行比较,但是最重要的错误是您没有为head分配内存,并且没有正确地初始化'head'。另外,完成后应该释放内存(我没有放入)。我也没有检查代码是否完全符合您的要求,但是可以运行以下代码:
#include<stdio.h>
#include<stdlib.h>
typedef struct nod {
int data;
struct nod *prev, *next;
} soldier;
soldier *head;
void create_soldier (int sequence) {
if(head->data == 0) { // when the linked list starts
head->data = sequence;
head->prev = NULL;
head->next = NULL;
}
else{
soldier *temp;
soldier *t;
temp= (soldier *) malloc(sizeof(soldier));
temp->data = sequence;
temp->next = NULL;
t = head; //Traversing
while (t->next != NULL)
t = t->next;
if(temp->data==1){ //for the rear end of the array to link back to the head
t->next = temp;
temp->prev = t;
temp->next = head;
head->prev = temp;
}
else{
t->next = temp;
temp->prev = t;
}
}
}
void display(soldier* head){
soldier *t;
t=head;
while (t->next != head){
printf("%d", t->data);
t= t->next;
}
}
int main()
{
int n, k;
printf("Enter the number of soldiers to be executed");
scanf("%d", &n);
printf("Enter the number of soldiers to be skipped");
scanf("%d", &k);
head = (soldier *) malloc(sizeof(soldier));
for ( ; n>= 1; n--)
create_soldier(n);
display(head);
free(head);
return 0;
}
答案 2 :(得分:1)
好像您正在解决Josephus Problem!
这里首先要解决各种编译问题。使用类似
的标志来编译代码-Wall -Wextra -Werror -O2 -std=c99 -pedantic
(如果尚未)。在编写代码时,请经常编译并运行。使用valgrind之类的工具来验证您的代码是否不是leak memory并帮助检测segmentation faults。
void soldier* create_soldier (int sequence)
是无效的函数,因为它指定了两种返回类型。它应该为void create_soldier(int sequence)
,因为它不会返回任何内容。display
被定义了两次。if(head->data==NULL)
比较int
和NULL
;您可能希望0
是有效的data
值,而意图可能是if (head == NULL)
。(head->data==NULL)
从create_solder
函数开始,但这会立即取消引用空指针。head
。它应该在main
范围内,并传递给需要它的任何函数。head
,例如,无法创建多个列表。尝试编写不会改变外部状态的pure functions。这样一来,程序就更不会出错,并且更易于推理。node
之类的通用名称,而不要使用soldier
。我们希望能够编写一个双向链接列表“类”,并将其重用于任何目的(例如解决此特定问题)。如果需要,只需添加现有typedef soldier
类型的node
别名即可。void create_soldier (int sequence)
并不是一个非常有用的功能,因为我们很少需要使用来自1..n
的数据来创建列表。更常见的是,我们只想创建一个node
并为其提供一些任意数据。考虑到这一点,我希望使用void create_node(node **head, int data)
,它只会创建一个node
。然后,我们可以在main
中运行循环,以根据问题规范创建n
节点(或为运行create_node
逻辑的1..n
编写包装函数)。for
循环优先于while
循环。它们更加干净,并且使变量的作用域范围小而紧凑。malloc
。这是一个重写建议:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *prev, *next;
} node;
void create_node(node **head, int data) {
if (*head) {
node *new_node = malloc(sizeof(*new_node));
new_node->data = data;
new_node->next = *head;
new_node->prev = (*head)->prev;
(*head)->prev->next = new_node;
(*head)->prev = new_node;
}
else {
*head = malloc(sizeof(**head));
(*head)->data = data;
(*head)->prev = *head;
(*head)->next = *head;
}
}
void display(node *head) {
node *t = head;
if (t) {
printf("%d->", t->data);
for (t = t->next; t != head; t = t->next) {
printf("%d->", t->data);
}
puts("");
}
}
void free_list(node *head) {
node *t = head;
if (t) {
for (t = t->next; t != head;) {
node *dead_node = t;
t = t->next;
free(dead_node);
}
free(head);
}
}
int main() {
int n;
node *head = NULL;
printf("Enter the number of soldiers to be executed: ");
scanf("%d", &n);
for (int i = 0; i < n; create_node(&head, ++i));
display(head);
free_list(head);
return 0;
}