【问题标题】:C: Enqueue() - Inserting at the end of a linked list, returning head of listC: Enqueue() - 在链表末尾插入,返回链表头
【发布时间】:2014-10-26 03:28:37
【问题描述】:

我对编程很陌生。尝试编写一个函数来接收列表的头部 + 要插入的数据 - 并传回列表的新头部。我已经通过在列表头部添加一个元素做了很多工作,但由于某种原因,我无法理解这种细微的差异。

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct node_{
    int data;
    struct node_ *next;
} Queue;

int main(void){

   Queue* queue = NULL;

   queue = enqueue(queue, 1);

   assert(queue->next == NULL);
   assert(queue->data == 1);

   queue = enqueue(queue, 2);

   assert(queue->data == 1);
   assert(queue->next != NULL);
   assert(queue->next->data == 2);

   free(queue->next);
   free(queue);

   return 0;

}

Queue *enqueue(Queue *queue, int data){

    Queue *new_node, *p;

    new_node = malloc(sizeof(Queue));

    new_node->data = data;
    new_node->next = NULL;

    p = queue;

    while(p->next != NULL){
        p = p->next;
    }

    p->next = new_node;

    return ??????

}

我知道要插入头部,你可以:

new_node->data = data; 
new_node->next = queue;
return new_node;

如果我上面写的没有多大意义,我深表歉意。我很累,我已经经历了很多次迭代。可能遗漏了一些明显的东西。

【问题讨论】:

    标签: c insert linked-list queue


    【解决方案1】:

    只需返回queue。您还必须测试输入 queue 是否为 NULL,在这种情况下,您显然无法访问 next 指针来查找结尾,因此在这种情况下只需返回新节点即可。

    Queue *enqueue(Queue *queue, int data){
    
        Queue *new_node, *p;
    
        new_node = malloc(sizeof(Queue));
        new_node->data = data;
        new_node->next = NULL;
    
        if (!queue)
            return new_node;
    
        p = queue;
        while (p->next)
            p = p->next;
        p->next = new_node;
    
        return queue;
    }
    

    【讨论】:

    • 所以 if(queue==NULL) 返回 new_node,对吗?但是下一部分呢?还是有点迷茫。我还需要while循环来单步执行列表吗?一旦 queue->next == NULL,返回队列?但是,呃,首先将 queue = 设置为 new_node ? 抓头 抱歉,太密集了!感谢您的帮助!
    • 如果队列为空,则没有理由(可能)循环遍历它。因此,只需在此时返回新节点。查看一些代码的更新答案。
    • 天哪,它奏效了。哈。现在试图更好地理解它。如果 queue = NULL,则返回 new_node。我明白了。如果 queue 不为 null,它会跳到列表的末尾并将 queue->next 分配给 queue。然后它将 new_node 分配给 queue->next... 并返回队列。这适用于超过 2 个元素吗?链接列表让我头疼。非常感谢您对 ooga 的帮助!
    【解决方案2】:

    当您发送头指针queue 时,您无需返回任何内容。


    #include<stdio.h>
    #include<stdlib.h>
    
    typedef struct node_{
        int data;
        struct node_ *next;
    } Queue;
    
    Queue * enqueue(Queue *queue, int data){
    
        Queue *new_node, *p;
    
        new_node = malloc(sizeof(Queue));
    
        new_node->data = data;
        new_node->next = NULL;
    
        p = queue;
    
        while(p->next != NULL){
            p = p->next;
        }
    
        p->next = new_node;
        p = new_node;
    
        return (queue);
    }
    
    void display(Queue *queue)
    {
        Queue *temp;
        for(temp=queue->next;temp!=NULL;temp=temp->next)
            printf("%d -> ",temp->data);
        printf("null \n");
    }
    
    int main(void){
    
        Queue *queue;
        queue = malloc(sizeof(Queue));
        queue->next = NULL;
        queue = enqueue(queue, 1);
        queue = enqueue(queue, 2);
        queue = enqueue(queue, 3);
        queue = enqueue(queue, 4);
        display(queue);
    }
    

    输出

    1 -> 2 -> 3 -> 4 -> null
    

    【讨论】:

    • 感谢您花时间回答我的问题!但是,如果我必须返回指向标头的指针,您会建议我如何继续?这就是为什么我一直在挣扎。我正在尝试完成一项可选的“预实验”任务,该任务旨在帮助我们为本周晚些时候的实验做准备。在赋值中,主要使用assert(queue->next == NULL);并在 queue = enqueue(queue,1) 之后断言(queue->data == 1) 以查看我们的函数是否正常工作。当我尝试实现您的逻辑,但最后返回 p 时,我得到一个段错误。我为我的迟钝道歉!感谢您的尝试!
    • 我编辑了我的主要功能以显示它的真实外观。它现在显示所有断言。当我尝试返回队列时,出现段错误。如果我将 main 更改为 queue->next = NULL,它可以工作,但是断言在 'queue->next == ((void *)0)' 失败时失败。中止,它说。不知道发生了什么。在更实际的情况下,我认为我了解正在发生的事情的要点,但我不确定为什么 p->next = new_node 和 p = new_node
    • @AzathothM:你能理解真是太好了。 p-&gt;next = new_node 这会将您的新节点添加到列表中,p = new_node 将向前移动 p 到下一个节点。
    • 您非常乐于助人。我实现了 ooga 的逻辑(如下)——它适用于 2 个元素,但当我尝试将 3 个等入队时似乎不起作用。是否可以继续以这种方式添加元素?我需要开始跟踪头部和尾部吗?我可以通过队列找到的大多数实现都有一个全局头/尾,所以我(以我的能力有限)很难用我在原帖中提到的限制来实现这个功能。
    • @AzathothM:不客气。在我发布的代码中尝试添加更多元素它会起作用。
    【解决方案3】:

    enqueue函数中:

    检查参数队列是否为NULL,第一次为真,应作为特例处理:

    if (queue == NULL) 
    {      
        p = new_node;
        p->next = NULL;
        return p;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-13
      • 2015-12-14
      • 1970-01-01
      • 1970-01-01
      • 2020-11-15
      • 2021-05-23
      • 2015-02-08
      相关资源
      最近更新 更多