【发布时间】:2021-09-16 12:46:45
【问题描述】:
我目前正在编写以下代码,以便在 C 中创建一个双向循环链表。当给定 2 或 3 个数字作为参数时,该代码确实有效,但从第四个数字开始,一些数字开始从新的出于某种奇怪的原因创建了列表。
#include <stdio.h>
#include <stdlib.h>
typedef struct s_node
{
int value; // each node contains a integer storing an arbitrary value
struct s_node *next;
struct s_node *prev;
} t_node;
static void create(t_node **head, t_node **tail, int value, int i)
{
t_node *tmp; // create temporary node
t_node *result; // create the new node
tmp = *head;
result = malloc(sizeof(t_node)); // malloc the new node
if (!result)
return ;
result->value = value;
result->next = NULL;
if (*head == NULL) // if the head is NULL, result is the first node to be added
{
result->prev = NULL;
*head = result;
return ;
}
while (tmp->next != NULL && i-- > 0)
tmp = tmp->next; // parse the linked list until the end
tmp->next = result; // set result as the next pointer to the last element of the linked list result->prev = tmp; // set the head has to the previous pointer of the new node
*tail = result; // tail is now the new node
(*tail)->next = *head; //link the tail's next pointer to the head to make it circular
(*head)->prev = *tail; // link the head's previous pointer to make it backwards circular
}
void save(t_node **head, t_node **tail, int argc, char **argv)
{
int i;
i = 1;
while (i < argc) // go through the list of given numbers as argument
{
create(head, tail, atoi(argv[i]), i); // append a new node to the linked list
i++;
}
}
int main(int argc, char **argv)
{
t_node *head;
t_node *tail;
t_node *tmp;
int i;
i = 4;
head = NULL;
tail = NULL;
if (argc == 0)
return (0);
save(&head, &tail, argc, argv);
tmp = head;
while (tmp->next != NULL && i-- > 0)
{
printf("%d - ", tmp->value);
tmp = tmp->next;
}
printf("\n");
return (0);
}
当使用如下两个参数编译和执行时:
./a.out 10 20
返回以下内容(正确):
10 - 20 - 10 - 20 -
当使用三个参数(10、20 和 30)执行时,会打印以下内容(正确):
10 - 20 - 30 - 10 -
但是,当将第四个数字添加到列表中时(10、20、30 和 40),将打印以下错误列表:
10 - 20 - 40 - 10 -
30 号消失了,我真的不明白为什么。有人可以帮我吗?
【问题讨论】:
-
你应该学习如何使用调试器逐行执行你的代码,检查每一步的变量以确保它们的值是你所期望的。
-
这绝对是一个公平的观点。我猜你说的是 Valgrind 还是 GDB?
-
新插入后的下一个节点不一定是头节点。您的
create似乎是“在任何地方插入”和“在末尾插入”的混合体。 -
你的描述让我吃惊。在循环双链表中,如果为空,则头和尾应指向第一个插入的新节点。如果不为空,则不需要迭代到末尾,因为 tail 和 head->prev 都应该指向它。请描述你所谓的双链循环列表的结构,对于没有节点,一个节点,两个节点和三个节点的情况。解释您希望每个指针指向的位置。
-
请解释为什么您认为循环列表中需要尾部引用?如果它真的是循环的,那么非空列表中的尾部总是等于
head->prev,那么你为什么要为此浪费一个单独的成员呢?为什么要测试tmp->next != NULL?在循环列表中没有NULL指针...您确定需要循环 列表,还是误解?
标签: c data-structures linked-list