【问题标题】:Inserting at head of linked list?在链表的头部插入?
【发布时间】:2021-02-07 17:09:50
【问题描述】:

我试图在链表的头部插入一个节点,但我不确定为什么这个函数不起作用。我认为这是一项相当简单的任务,但我似乎在这里遗漏了一些东西。我还包含了我的结构和 main 的一部分,以便您可以更清楚地了解代码。谢谢

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

typedef struct LinkedList
{
  node *head;
  node *tail;
} LinkedList;

LinkedList *create_list(void)
{
  return calloc(1, sizeof(LinkedList));
}

node *create_node(int data)
{
  node *ptr = calloc(1, sizeof(node));
  ptr->data = data;

  return ptr;
}

void head_insert(LinkedList *list, int data) // problem
{
  node *newHead = create_node(data);
  newHead->next = list->head;
}

void print_list_helper(node *head)
{
  if (head == NULL)
    return;
  printf("%d%c", head->data, (head->next == NULL) ? '\n' : ' ');
  print_list_helper(head->next);
}

void print_list(LinkedList *list)
{
  if (list == NULL || list->head == NULL)
    return;
  print_list_helper(list->head);
}

int main(void)
{
  LinkedList *list = create_list();
  head_insert(list, 8);
  print_list(list); // print linked list function

  return 0;
}

所以我创建了一个新节点,并将 node->next 设置在列表的开头。我不确定我还缺少什么。我有另一个打印列表的函数,这就是该函数无效的原因。

【问题讨论】:

  • node *newHead = create_node(data); newHead->next = list->head;。一旦函数结束,你认为newHead 会发生什么?它消失了。没有人/变量不再引用它。您需要以一种或另一种方式将新头返回给调用者。
  • 调用head_insert() 的代码如何知道现在是列表头部的新节点?你没有改变list->head,是吗?不过,你应该,不是吗?这是列表处理代码的一个非常常见的问题。由于您拥有LinkedList 结构,因此它实际上更容易解决。通常,人们只是使用指向node 的指针,然后你必须更加努力。
  • 第一次在head_insert()list->headhead == NULL 的问题。

标签: c linked-list nodes


【解决方案1】:

head_insert() 函数定义的末尾添加这些行:

if (list->head == NULL)
{
    list->tail = newHead;
}
list->head = newHead;

在您的函数中,在头部添加新节点后,结构 LinkedList 仍指向前一个头部。您应该将该头更改为新插入的头。如果列表中没有节点,您还应该设置新创建的头 这是完整的功能。

void head_insert(LinkedList *list, int data)
{
  node *newHead = create_node(data);
  newHead->next = list->head;
  if (list->head == NULL)
  {
    list->tail = newHead;
  }
  list->head = newHead;
}

【讨论】:

  • 由于使用了node *tail;指针,所以必须在添加节点之前检查list->head是否为NULL,在这种情况下设置list->head = list->tail = newHead;来初始化tail指针。跨度>
  • @DavidC.Rankin 谢谢,我没有注意到。但是tail不应该一直被修改。仅当没有节点作为头/尾时才应修改它。因为我们只在第一个位置插入。第一次插入后,尾巴总是一样的。我已经修改了我的代码。
  • 我将代码编写为if (list->tail == NULL) list->tail = newHead;,测试并分配给同一个成员,而不是测试head 并分配给tail。感觉更加一致。结果是一样的。
  • @JonathanLeffler 如果我们这样做并且尾部以某种方式变为空,则下一次插入将使新插入的节点成为尾部并导致不一致。否则你应该检查tail是否为空,如果是,你应该遍历列表并将最后一个元素添加为tail。
  • 你可以这样想。 tail 指针始终指向列表中的最后一个节点。这允许在末尾进行 O(1) 插入,而无需遍历列表。当插入第一个节点时,headtail 都指向同一个节点。然后添加下一个节点时,您执行tail->next = newnode; tail = newnode; 添加新头时,如果head 不是NULL,则只是newnode->next = head; head = newnode; 在这种情况下,tail 不会更改。查看原始问题下我评论中的链接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-18
  • 2021-03-24
  • 2013-09-12
  • 2018-04-05
  • 1970-01-01
相关资源
最近更新 更多