C中的链表:删除第二个节点并释放内存

C中的链表:删除第二个节点并释放内存,c,linked-list,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

出于某种原因,如果我有一个看起来像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;
}
#包括
#包括
类型定义结构列表节点{
int数据;
结构ListNode*next;
}*LinkedList;
int deleteSecond(链接列表){
如果(列表==NULL | |列表->下一步==NULL)
返回0;
int val=列表->下一步->数据;
LinkedList second=列表->下一步;
列表->下一步=列表->下一步->下一步;
免费(第二);
返回val;
}
int main(){
LinkedList head=NULL;
head=malloc(sizeof(LinkedList));
对于(int i=0;i<4;i++){
LinkedList newNode=malloc(sizeof(LinkedList));
newNode->data=i;
新建节点->下一步=头部;
头=新节点;
}
LinkedList ptr=头;
对于(int i=0;i<4;i++){
printf(“%d\n”,ptr->data);
ptr=ptr->next;
}
printf(“\n”);
第二名(负责人);
while(head!=NULL){
printf(“%d\n”,头部->数据);
头部=头部->下一步;
}
返回0;
}

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

您正在创建一个空节点
,这造成了问题。最后一个节点应指向
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;
  }
LinkedList头=NULL;
//head=malloc(sizeof(LinkedList));
对于(int i=0;i<4;i++){
LinkedList newNode=malloc(sizeof(LinkedList));
newNode->data=i;
新建节点->下一步=头部;
头=新节点;
}

您正在创建一个空节点
头部
,这会产生问题。最后一个节点应指向
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;
  }
LinkedList头=NULL;
//head=malloc(sizeof(LinkedList));
对于(int i=0;i<4;i++){
LinkedList newNode=malloc(sizeof(LinkedList));
newNode->data=i;
新建节点->下一步=头部;
头=新节点;
}
这是错误的。正确的答案是

head = malloc(sizeof(*head));
LinkedList newNode = malloc(sizeof(*newNode));
然后又是同样的方式

head = malloc(sizeof(*head));
LinkedList newNode = malloc(sizeof(*newNode));
现在让我们看看你在这里做了什么

头的数据或链接属性从未初始化。因此,访问它时会出现未定义的行为

如果要将内存分配给
,则需要编写此代码

...
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;
}
有两件事你可以考虑

  • 不要在typedef下隐藏指针
  • Do检查
    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;
}
#包括
#包括
类型定义结构列表节点{
int数据;
结构ListNode*next;
}列表节点;
作废freeMemList(列表节点*头){
ListNode*temp;
while(head!=NULL){
温度=水头;
头部=头部->下一步;
免费(临时);
}
}
int deleteSecond(ListNode*列表){
如果(列表==NULL | |列表->下一步==NULL)
返回0;
int val=列表->下一步->数据;
ListNode*second=列表->下一步;
列表->下一步=列表->下一步->下一步;
免费(第二);
返回val;
}
作废打印列表(列表节点*头){
while(head!=NULL){
printf(“%d\n”,头部->数据);
头部=头部->下一步;
}
}
结构ListNode*addNodes(结构ListNode*head,int n){
对于(大小i=0;idata=i;
新建节点->下一步=头部;
头=新节点;
}
回流头;
}
内部主(空){
ListNode*head=NULL;
head=添加节点(head,4);
印刷品清单(标题);
printf(“*********\n”);
int valDeleted=deletessecond(head);
printf(“%s%d\n”,“值已删除”,值已删除);
印刷品清单(标题);
自由成员名单(标题);
返回0;
}
这是错误的。正确的答案是

head = malloc(sizeof(*head));
LinkedList newNode = malloc(sizeof(*newNode));
然后又是同样的方式

head = malloc(sizeof(*head));
LinkedList newNode = malloc(sizeof(*newNode));
现在让我们看看你在这里做了什么

头的数据或链接属性从未初始化。因此,访问它时会出现未定义的行为

如果要将内存分配给
,则需要编写此代码

...
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;
}
有两件事你可以考虑

  • 不要在typedef下隐藏指针
  • Do检查
    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;
}
#包括
#包括
类型定义结构列表节点{
int数据;
结构ListNode*next;
}列表节点;
作废freeMemList(列表节点*头){
ListNode*temp;
while(head!=NULL){
温度=水头;
头部=头部->下一步;
免费(临时);
}
}
int deleteSecond(ListNode*列表){
如果(列表==NULL | |列表->下一步==NULL)
返回0;
int val=列表->下一步->数据;
ListNode*second=列表->下一步;
列表->下一步=列表->下一步->下一步;
免费(第二);
返回val;
}
作废打印列表(列表节点*头){
while(head!=NULL){
printf(“%d\n”,头部->数据);
头部=头部->下一步;
}
}
结构ListNode*addNodes(结构ListNode*head,int n){
对于(大小i=0;idata=i;
新建节点->下一步=头部;
头=新节点;
}
回流头;
}
内部主(空){
ListNode*head=NULL;
head=添加节点(he)