web-dev-qa-db-fra.com

C liste chaînée insérant un noeud à la fin

J'ai des problèmes avec ma méthode d'insertion pour une liste chaînée en C. Il semble ne faire qu'ajouter au début de la liste. Toute autre insertion que je fais échoue. Et ce débogueur CodeBlocks est si difficile à comprendre que je ne l’ai toujours pas compris. Cela ne me donne jamais de valeur, juste des adresses en mémoire. En tout cas c'est ma fonction. Voyez-vous une raison pour laquelle cela échoue? 

/* function to add a new node at the end of the list */
int addNodeBottom(int val, node *head){

    //create new node
    node *newNode = (node*)malloc(sizeof(node));

    if(newNode == NULL){
        fprintf(stderr, "Unable to allocate memory for new node\n");
        exit(-1);
    }

    newNode->value = val;

    //check for first insertion
    if(head->next == NULL){
        head->next = newNode;
        printf("added at beginning\n");
    }

    else
    {
        //else loop through the list and find the last
        //node, insert next to it
        node *current = head;
        while(current->next != NULL)
        {
            if(current->next == NULL)
            {
                current->next = newNode;
                printf("added later\n");
            }
            current = current->next;
        }
    }
    return 0;
}

Ensuite, dans la partie principale, seul 929 est ajouté.

   //testing addNodeBottom function
    addNodeBottom(929, head);
    addNodeBottom(98, head);
    addNodeBottom(122, head);
    addNodeBottom(11, head);
    addNodeBottom(1034, head);
8
Tony

Ce code fonctionnera. La réponse de samplebias est presque correcte, mais vous avez besoin d'un troisième changement:

int addNodeBottom(int val, node *head){

    //create new node
    node *newNode = (node*)malloc(sizeof(node));

    if(newNode == NULL){
        fprintf(stderr, "Unable to allocate memory for new node\n");
        exit(-1);
    }

    newNode->value = val;
    newNode->next = NULL;  // Change 1

    //check for first insertion
    if(head->next == NULL){
        head->next = newNode;
        printf("added at beginning\n");
    }

    else
    {
        //else loop through the list and find the last
        //node, insert next to it
        node *current = head;
        while (true) { // Change 2
            if(current->next == NULL)
            {
                current->next = newNode;
                printf("added later\n");
                break; // Change 3
            }
            current = current->next;
        };
    }
    return 0;
}

Modification 1: newNode->next doit être défini sur NULL pour ne pas insérer de pointeurs non valides à la fin de la liste.

Changement 2/3: la boucle est changée en une boucle sans fin qui sera sautée avec break; lorsque nous aurons trouvé le dernier élément. Notez comment while(current->next != NULL) a contredit if(current->next == NULL) avant.

EDIT: En ce qui concerne la boucle while, cette méthode est bien meilleure:

  node *current = head;
  while (current->next != NULL) {
    current = current->next;
  }
  current->next = newNode;
  printf("added later\n");
12
schnaader

Une fois que vous avez malloc et node, assurez-vous de définir node->next = NULL.

int addNodeBottom(int val, node *head)
{    
    node *current = head;
    node *newNode = (node *) malloc(sizeof(node));
    if (newNode == NULL) {
        printf("malloc failed\n");
        exit(-1);
    }    

    newNode->value = val;
    newNode->next = NULL;

    while (current->next) {
        current = current->next;
    }    
    current->next = newNode;
    return 0;
}    

Je dois préciser qu'avec cette version, la head est toujours utilisée comme mannequin et non pour stocker une valeur. Cela vous permet de représenter une liste vide en ayant simplement un nœud head.

2
samplebias

Je voudrais mentionner la clé avant d’écrire le code pour votre considération. 

//Clé

temp = adresse du nouveau noeud alloué par la fonction malloc (bibliothèque membre od alloc.h en C)

prev = adresse du dernier noeud de la liste de liens existante.

next = contient l'adresse du prochain noeud 

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

void addnode_end(int a) {
    struct node *temp, *prev;
    temp = (struct node*) malloc(sizeof(node));
    if (temp == NULL) {
        cout << "Not enough memory";
    } else {
        node->data = a;
        node->next = NULL;
        prev = head;

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

        prev->next = temp;
    }
}
0
user2800488

Cela fonctionne bien:

struct node *addNode(node *head, int value) {
    node *newNode = (node *) malloc(sizeof(node));
    newNode->value = value;
    newNode->next = NULL;

    if (head == NULL) {
        // Add at the beginning
        head = newNode;
    } else {
        node *current = head;

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

        // Add at the end
        current->next = newNode;
    }

    return head;
}

Exemple d'utilisation:

struct node *head = NULL;

for (int currentIndex = 1; currentIndex < 10; currentIndex++) {
    head = addNode(head, currentIndex);
}
0
BullyWiiPlaza

Le nouveau nœud est toujours ajouté après le dernier nœud de la liste liée donnée. Par exemple, si la liste chaînée donnée est 5-> 10-> 15-> 20-> 25 et que nous ajoutons un élément 30 à la fin, la liste chaînée devient 5-> 10-> 15-> 20-> 25- > 30 . Comme une liste chaînée est généralement représentée par son en-tête, nous devons parcourir la liste jusqu'à la fin, puis changer le prochain du dernier nœud en nouveau nœud.

/* Given a reference (pointer to pointer) to the head
   of a list and an int, appends a new node at the end  */


    void append(struct node** head_ref, int new_data)
    {
    /* 1. allocate node */
         struct node* new_node = (struct node*) malloc(sizeof(struct node));

        struct node *last = *head_ref;  /* used in step 5*/

    /* 2. put in the data  */
        new_node->data  = new_data;

    /* 3. This new node is going to be the last node, so make next 
          of it as NULL*/
        new_node->next = NULL;

    /* 4. If the <a href="#">Linked List</a> is empty, then make the new node as head */
        if (*head_ref == NULL)
        {
       *head_ref = new_node;
       return;
        }  

    /* 5. Else traverse till the last node */
        while (last->next != NULL)
        last = last->next;

    /* 6. Change the next of last node */
        last->next = new_node;
        return;    
}
0
Nikhil Sharma