如何在链接列表的开头添加元素而不替换当前的第一个元素?

问题描述

我有以下struct元素:

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;
}

解决方法

在您的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)插入您的需求发生变化时,列表中的第一个。

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