【问题标题】:Assigning NULL to the head node in a linked list in C将NULL分配给C中链表中的头节点
【发布时间】:2019-06-09 18:18:54
【问题描述】:

请查看下面的完整代码。

我有一个名为arr 的初始数组。 我正在使用链接列表通过append 函数存储一些索引。获得索引后,我将它们存储在链表中并使用clearList 将相应的值更改为 0(在此示例中为 arr[2] 和 arr[4])。 最后,我通过调用freeList 来释放内存,因为我已经完成了链接列表。

但是,为了能够一次又一次地做同样的事情,每当我调用freeList 时,我都需要将head 设置为NULL。但是我不能。知道如何解决这个问题吗? 谢谢你。

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

【问题讨论】:

  • 追加时如何更改head的值?也许这种方式也可以用于删除......
  • 我没有改变 head 的值,它总是保持不变。我只将新节点添加到列表中。
  • 如果您从不更改 head 的值,它将是 NULL 并且您的列表将为空......所以您的 append 函数必须以某种方式更改它
  • 正确。我通过head_refappend 中执行此操作。但是,在freeList 中,我释放了头部,这使情况变得复杂。
  • 如果您将head 的地址传递给freeList,您可以在freeList 中将其设置为NULL。否则,您必须在调用clearList 之后执行head = NULL;。您还可以创建一个预处理器宏,例如clearListNull 两者兼得。

标签: c function pointers linked-list reference


【解决方案1】:

仅出于完整性考虑:另一种可能的选择是为 freeList() 使用包装宏。

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

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

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

此解决方案与返回修改后指针的版本有类似的缺点。您可以简单地忘记使用正确的呼叫freeListNull(head); 并改为呼叫freeList(head);。最好的解决方案是一个函数freeList(),它将head指针的地址作为idk的答案。

【讨论】:

    【解决方案2】:

    您已经在 append 函数中更改了 head 的值,因此您基本上需要在 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 */
        }
    

    【讨论】:

      【解决方案3】:

      我意识到可以更改 freeList 函数,使其返回 NULL 值。请参阅下面的更新代码:

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

      【讨论】:

      • 旁白:为什么new_node = (struct Node*) malloc(sizeof(struct Node)) 中不需要的演员阵容?考虑new_node = malloc(sizeof *new_node)arr = malloc(sizeof *arr * 10); 等等。更容易正确编码、审查和维护。
      • 我认为 idk 的解决方案更好,因为没有什么能阻止您在代码中调用 freeList(head); 甚至 (void)freeList(head);
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-17
      • 2017-01-29
      • 1970-01-01
      • 2011-05-28
      • 2023-03-25
      相关资源
      最近更新 更多