1
votes

Assigner NULL au nœud principal dans une liste chaînée en C

Veuillez consulter le code complet ci-dessous.

J'ai un tableau initial nommé arr . J'utilise une liste liée pour stocker certains index via la fonction append . Après avoir obtenu les indices, je les stocke dans une liste chaînée et utilise clearList pour changer les valeurs correspondantes à 0 (dans cet exemple arr [2] et arr [4]). Enfin, je libère la mémoire en appelant freeList car j'ai fini avec la liste chaînée.

Cependant, pour pouvoir faire la même chose encore et encore, je dois mettre head à NULL chaque fois que j'appelle freeList . Mais je ne peux pas. Aucune idée sur la façon de résoudre ça? Merci.

#include <stdio.h>  
#include "gurobi_c.h"
#include <stdlib.h>

//Gurobi variables
GRBenv   *env = NULL;
GRBmodel *model = NULL;
//Gurobi variables

struct Node 
{ 
  int data; 
  struct Node *next;
  struct Node *end;
};

void append(struct Node** head_ref, int new_data) 
    { 
    struct Node *last = *head_ref;  
    struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));  
    new_node->data  = new_data; 
    new_node->next = NULL;
    new_node->end = new_node;
    if (*head_ref == NULL) 
    { 
       *head_ref = new_node;
       //printf("  ..Init Append %d\n",new_data);
       return; 
    } 
    last = (*head_ref)->end; 
    last->next = new_node;  
    (*head_ref)->end=new_node;
    //printf("  ..Append %d\n",new_data);
    return; 
} 

void clearList(struct Node *node, double *arr) 
    { 
    int i;
    if(node!=NULL)
        {
        struct Node tmp;
        tmp=*(node->end);
        while (node != NULL) 
            {  
            i=node->data;
            arr[i]=0;
            //printf("   ..clear %d \n", node->data,(node->end)->data);
            node = node->next; 
            }
        }
    }

void freeList(struct Node *node) 
    { 
    struct Node *tmp,*hd;
    hd=node;
    while (node != NULL) 
        { 
        tmp=node;
        node = node->next; 
        //printf("  ..Free %d \n", tmp->data);      
        free(tmp);
        } 
    hd=NULL;
    }

int main (){
    Node *head;     
    double *arr = (double *) malloc(sizeof(double) * 10);
    for(int i=0;i<10;i++)
        arr[i]=i;

    head=NULL;
    printf("Head:  %s\n", head);
    append(&head,2);
    append(&head,4);
    clearList(head,arr);
    for(int i=0;i<10;i++)
        printf("No %d : %.2f\n",i,arr[i]);
    freeList(head);

    free(arr);

    printf("%s", head);
    getchar();
    return 0;
    }


6 commentaires

Comment changer la valeur de head lors de l'ajout? Peut-être que cette méthode pourrait également être utilisée pour la suppression ...


Je ne change pas la valeur de la tête, elle reste toujours la même. J'ajoute uniquement de nouveaux nœuds à la liste.


Si vous ne changez jamais la valeur de head , ce serait NULL et votre liste serait vide ... donc votre fonction append doit changer ça en quelque sorte


Correct. Je fais cela par head_ref dans append . Cependant, dans freeList , je libère la tête, ce qui complique la situation.


Si vous passiez l'adresse de head à freeList , vous pouvez la définir sur NULL dans freeList . Sinon, vous devrez faire head = NULL; après avoir appelé clearList . Vous pouvez également créer une macro de préprocesseur, par exemple clearListNull qui fait les deux.


@Bodo Pourriez-vous expliquer comment faire cela exactement s'il vous plaît? Mon problème est que je sais que cela pourrait être fait en manipulant des adresses, mais je ne peux pas le faire fonctionner. Je trouve un peu une solution alternative mais j'aimerais apprendre à bien faire les choses.


3 Réponses :


0
votes

J'ai réalisé qu'il était possible de changer la fonction freeList afin qu'elle renvoie une valeur NULL. Voir le code mis à jour ci-dessous:

#include <stdio.h>  
#include "gurobi_c.h"
#include <stdlib.h>

//Gurobi variables
GRBenv   *env = NULL;
GRBmodel *model = NULL;
//Gurobi variables

struct Node 
{ 
  int data; 
  struct Node *next;
  struct Node *end;
};

void append(struct Node** head_ref, int new_data) 
    { 
    struct Node *last = *head_ref;  
    struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));  
    new_node->data  = new_data; 
    new_node->next = NULL;
    new_node->end = new_node;
    if (*head_ref == NULL) 
    { 
       *head_ref = new_node;
       //printf("  ..Init Append %d\n",new_data);
       return; 
    } 
    last = (*head_ref)->end; 
    last->next = new_node;  
    (*head_ref)->end=new_node;
    //printf("  ..Append %d\n",new_data);
    return; 
} 

void clearList(struct Node *node, double *arr) 
    { 
    int i;
    if(node!=NULL)
        {
        struct Node tmp;
        tmp=*(node->end);
        while (node != NULL) 
            {  
            i=node->data;
            arr[i]=0;
            //printf("   ..clear %d \n", node->data,(node->end)->data);
            node = node->next; 
            }
        }
    }

Node* freeList(struct Node *node) 
    { 
    struct Node *tmp;
    while (node != NULL) 
        { 
        tmp=node;
        node = node->next; 
        printf("  ..Free %d \n", tmp->data);      
        free(tmp);
        } 
    return NULL;
    }

int main (){
    Node *head;     
    double *arr = (double *) malloc(sizeof(double) * 10);
    for(int i=0;i<10;i++)
        arr[i]=i;

    head=NULL;
    printf("Head:  %s -> null as expected\n", head);
    append(&head,2);
    append(&head,4);
    clearList(head,arr);
    for(int i=0;i<10;i++)
        printf("No %d : %.2f\n",i,arr[i]);

    printf("Head:  %s -> Not null as linkedlist is not freed\n", head);
    head=freeList(head);
    printf("Head:  %s -> Again null as expected\n", head);
    free(arr);
    printf("%s", head);
    getchar();
    return 0;
    }


2 commentaires

A part: Pourquoi le cast inutile dans new_node = (struct Node *) malloc (sizeof (struct Node)) ? Considérez new_node = malloc (sizeof * new_node) . arr = malloc (sizeof * arr * 10); etc. à la place. Plus facile à coder correctement, à réviser et à maintenir.


Je pense que la solution d'idk est meilleure car rien ne vous empêche d'appeler freeList (head); ou même (void) freeList (head); dans votre code.



3
votes

Vous modifiez déjà la valeur de head dans votre fonction append , vous devez donc faire la même chose dans freeList :

void freeList(struct Node **head_ref) 
    { 
    struct Node *tmp,*node;
    node=*head_ref;
    while (node != NULL) 
        { 
        tmp=node;
        node = node->next; 
        //printf("  ..Free %d \n", tmp->data);      
        free(tmp);
        } 
    *head_ref=NULL;
    }

int main (){
    /* do stuff */
    freeList(&head);
    /* do stuff */
    }


0 commentaires

1
votes

Juste pour être complet: une autre option possible serait d'utiliser une macro wrapper pour freeList().

void freeList(struct Node *node) 
{ 
    /* ... */
}

#define freeListNull(node) do { \
    freeList(node); \
    node = NULL; \
} while(0)

int main () {
    /* ... */
    freeListNull(head);
    /* ... */
}

Cette solution a un inconvénient similaire à la version qui renvoie le pointeur modifié. Vous pouvez simplement oublier d'utiliser le bon appel freeListNull (head); et appeler freeList (head); à la place. La meilleure solution est une fonction freeList () qui prend l'adresse du pointeur head comme dans la réponse d'idk.


0 commentaires