C中的链接列表:删除第二个节点和空闲内存

时间:2017-12-11 20:27:19

标签: c linked-list

出于某种原因,如果我有一个看起来像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-&gt; next = head-&gt; next-&gt; next,然后我将指针释放到第二个节点。我不知道为什么我在列表末尾有两个0。

2 个答案:

答案 0 :(得分:2)

您正在创建一个正在创建问题的空节点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; } 是正确的。

{{1}}

答案 1 :(得分:1)

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作为LinkedListstruct LinkedNode*并且不分配任何内存它。它建议我们可以消除并简单地使用指向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;
}