【问题标题】:Linked List in C: Delete Second Node and Free MemoryC中的链表:删除第二个节点并释放内存
【发布时间】:2017-12-11 20:27:19
【问题描述】:

由于某种原因,如果我有一个看起来像 3->2->1->0 的链表,并且我调用了 deleteSecond(head),我会得到 3->1->0->0。这是我的代码:

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

typedef struct ListNode {
  int data;
  struct ListNode *next;
} *LinkedList;

int deleteSecond(LinkedList list) {
  if (list == NULL || list->next == NULL)
    return 0;
  int val = list->next->data;
  LinkedList second = list->next;
  list->next = list->next->next;
  free(second);
  return val;
}

int main() {
  LinkedList head = NULL;
  head = malloc(sizeof(LinkedList));
  for (int i = 0; i < 4; i++) {
    LinkedList newNode = malloc(sizeof(LinkedList));
    newNode->data = i;
    newNode->next = head;
    head = newNode;
  }
  LinkedList ptr = head;
  for (int i = 0; i < 4; i++) {
    printf("%d\n", ptr->data);
    ptr = ptr->next;
  }
  printf("\n");
  deleteSecond(head);
  while (head != NULL) {
    printf("%d\n", head->data);
    head = head->next;
  }
  return 0;
}

我相信我的 deleteSecond 函数应该是正确的。我创建一个指向我的第二个节点的指针,然后创建 head->next = head->next->next,然后释放指向第二个节点的指针。我不知道为什么我的列表末尾有两个 0。

【问题讨论】:

  • 为什么你 typedef 一个指针?这……嗯……你现在明白了……很难处理
  • head = malloc(sizeof(LinkedList)); 在这里你做了你不应该做的事。
  • 总是使用head = malloc(sizeof *head);,这样可以避免这个问题,也可以避免重新输入正确的类型名称……当然,只要你记得那个星号。 :)
  • 问题是你在循环之前分配了head,而你从来没有为它的data或next分配任何东西。在进入填充列表的循环之前,您应该将head 设置为NULL。这将解决问题 (demo)。
  • 一方面,。删除一个元素后,你应该循环 3 次,而不是 4 次。更好

标签: c linked-list


【解决方案1】:

您正在创建一个空节点head,这会产生问题。您的最后一个节点应指向NULL。所以初始化head = NULL是正确的。

  LinkedList head = NULL;
//  head = malloc(sizeof(LinkedList));
  for (int i = 0; i < 4; i++) {
    LinkedList newNode = malloc(sizeof(LinkedList));
    newNode->data = i;
    newNode->next = head;
    head = newNode;
  }

【讨论】:

    【解决方案2】:
    head = malloc(sizeof(LinkedList));
    

    这是错误的。正确的是

    head = malloc(sizeof(*head));
    

    然后还是一样

    LinkedList newNode = malloc(sizeof(*newNode));
    

    现在让我们看看你在这里做了什么。

    head 的数据或链接属性永远不会被初始化。所以你会得到未定义的行为来访问它。

    如果您想将内存分配给head,这是您要编写的代码。

    ...
    int main(void) {
      LinkedList head = NULL;
      head =  malloc(sizeof(*head));
      if( head == NULL){
        fprintf(stderr, "%s\n","Error in malloc" );
        exit(1);
      }
      head->next = NULL;
      head->data = 2017; // dummy data.
      for (int i = 0; i < 4; i++) {
        LinkedList newNode = malloc(sizeof(*newNode));
        if( newNode == NULL){
            fprintf(stderr, "%s\n","Error in malloc" );
            exit(1);
        }
        newNode->data = i;
        newNode->next = head;
        head = newNode;
      }
      ...
      ...
      deleteSecond(head);
      while (head != NULL) {
        printf("%d\n", head->data);  // prints 2017 also. But deletes the node that was in second position.
        head = head->next; 
      }
      return 0;
    }
    

    这里我们使用了一个额外的节点来保存虚拟数据。是的!这不是必需的。这个虚拟节点除了为newNodes 提供下一个链接之外没有做任何重要的事情,如果您只是将head 用作LinkedList 或struct LinkedNode* 并且不为其分配内存,则不需要此链接。这表明我们可以消除 than 并简单地使用指向 struct ListNode 的指针,即 head。

    那么代码会很简单

    LinkedList head = NULL;
    
      for (int i = 0; i < 4; i++) {
        LinkedList newNode =  malloc(sizeof(*newNode));
        if( newNode == NULL){
            fprintf(stderr, "%s\n","Error in malloc" );
            exit(1);
        }
        newNode->data = i;
        newNode->next = head;
        head = newNode;
      }
    

    你可以考虑几件事

    • 不要在 typedef 下隐藏指针。
    • 请检查malloc的返回值。
    • 请在完成使用后释放您分配的内存。

    代码也可以这样写。不使用typedef下的指针,将可复用的代码模块化。

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct ListNode {
        int data;
        struct ListNode *next;
    } ListNode;
    void freeMemList(ListNode *head){
        ListNode *temp;
        while(head!=NULL){
           temp = head;
           head = head->next;
           free(temp);
       }
    }
    int deleteSecond(ListNode * list) {
        if (list == NULL || list->next == NULL)
             return 0;
        int val = list->next->data;
        ListNode * second = list->next;
        list->next = list->next->next;
        free(second);
        return val;
    }
    void printList(ListNode *head){
        while (head != NULL) {
            printf("%d\n", head->data);
            head = head->next;
        }
    }
    struct ListNode * addNodes(struct ListNode* head, int n){
        for (size_t i = 0; i < n; i++) {
            ListNode * newNode = malloc(sizeof(*newNode));
            if( newNode == NULL){
                fprintf(stderr, "%s\n","Error in malloc" );
                exit(1);
            }
            newNode->data = i;
            newNode->next = head;
            head = newNode;
        }
        return head;
    }
    int main(void) {
        ListNode * head = NULL;
    
        head = addNodes(head,4); 
    
        printList(head);
        printf("********\n");
        int valDeleted = deleteSecond(head);
        printf("%s %d\n","Value deleted ", valDeleted );
        printList(head);
        freeMemList(head);
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2020-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-18
      • 2015-01-26
      • 2023-03-08
      • 2017-02-22
      • 1970-01-01
      相关资源
      最近更新 更多