【问题标题】:How to add an element at the begining of a linked list without replacing the current first element?如何在链表的开头添加一个元素而不替换当前的第一个元素?
【发布时间】:2020-10-19 08:24:24
【问题描述】:

我有以下结构元素:

typedef struct struct_element{
    Tache t;
    struct struct_element *suivant;
}Element;
typedef Element* Liste;

我正在尝试创建一个函数“ajoutdeb”,它应该创建一个新元素,并使列表的当前第一个元素成为新元素的下一个元素。这样新元素将被放置在链表的开头。这是我的实现:

void ajoutdeb(Liste* l, Tache t)
{
    Element e; 
    e.t = t;
    e.suivant = *l;
    *l = &e;
}

我的问题是新元素的下一个元素是它自己。我的函数逻辑有什么问题?

示例代码:

#include <stdio.h>
typedef struct{
  int no; /*le nom de la tache*/
  int duree; /* la duree de la tache*/
  int nbPred;     /* le nombre effectif de predecesseur de la tache*/
  int pred[16];  /*le tableau des predecesseurs*/
  char titre[256];   /*le titre de la tache*/
}Tache;

typedef struct struct_element{
    Tache t;
    struct struct_element *suivant;
}Element;

typedef Element* Liste;

void ajoutdeb(Liste* l, Tache t)
{
    Element e;
    e.t = t;
    e.suivant = *l;
    *l = &e;
}

int main()
{
    int nb;
    Liste liste = NULL;

    Tache t1 = {
            .titre = "Init",
            .no = 0
    };
    Tache t2 = {
            .titre = "Deuxième",
            .no = 1
    };

    ajoutdeb(&liste, t1);
    ajoutdeb(&liste, t2);

    return 0;
}

【问题讨论】:

  • 一个问题是变量e存在于栈中,因此函数结束后将无法访问。
  • 请发送minimal reproducible example。问题在显示的代码中,但为了解释问题,我们需要一个通用的上下文来参考。
  • 你展示的新代码不应该有你描述的问题。您如何检查问题?
  • 谢谢。看起来通过动态分配 e 我的问题解决了
  • 那么请不要修改问题中的代码。它使这个问题对其他人来说完全毫无价值,因为它实际上并没有描述问题。

标签: c pointers linked-list


【解决方案1】:

在ajoutdeb() 函数中,您需要返回类型才能指示向调用函数添加新节点的成功或失败。将返回类型设为指向节点的指针是一个不错的选择。失败时,您可以返回NULL,成功时,您可以返回列表的新头节点。

您的ajoutdeb() 函数需要:

  1. 为新节点分配和验证存储;
  2. 完全初始化指向该节点的值和指针;和
  3. 插入新节点作为列表的新头(称为前向链接节点)

由于您为新节点分配,您必须验证分配成功,然后再继续执行您的函数。如果分配失败,返回NULL表示失败。如果成功,您可以完成将节点添加到列表中。

总而言之,你可以做类似的事情:

Element *ajoutdeb(Element **l, Tache t)
{
    Element *e = malloc (sizeof *e);
    
    if (!e) {               /* validate EVERY allocation */
        perror ("malloc-e");
        return NULL;        /* return NULL on failure */
    }
    
    e->t = t;               /* fully initialize new node */
    e->suivant = NULL;
    
    e->suivant = *l;        /* make e->suivant point to list */
    *l = e;                 /* update list pointer to current */
    
    return *l;      /* return new head node on success */
}

(注意:避免类型定义指针。这隐藏了一定程度的间接性。虽然在 60 行代码中,可能很容易看到屏幕顶部会想起 Liste 实际上是键入Element*,但在处理多种类型的指针和间接级别时,向下6000行变得越来越困难。请参阅Is it a good idea to typedef pointers?)

您可能需要检查 Singly Linked List (node only, no wrapper) 以了解其他实现细节,然后查看 Singly Linked List of Integers (example) 以了解在您需要时使用 tail 指针在列表末尾提供 O(1) 插入的好处改变。

如果您还有其他问题,请告诉我。

【讨论】:

    猜你喜欢
    • 2019-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-27
    • 2014-04-15
    • 2021-06-08
    • 2011-09-07
    相关资源
    最近更新 更多