Я практикуюсь в реализации кода связанного списка. поэтому я пишу код:
файл LinkedList.c
#include <stdio.h>
#include "function.h"
int main(void) {
//initialize
struct Node myNode = { 10,NULL };
List head = &myNode;
insert(20, head, head);
makeEmpty(head);
return 0;
}
файл function.h
//this is the statement of the Linkedlist
#ifndef _FUNCTION_H
#define _FUNCTION_H
struct Node;
//pointer to the strcut Node
typedef struct Node* PtrToNode;
typedef PtrToNode List;
typedef PtrToNode Position;
struct Node
{
//a struct pointer that point to next struct
int element;
//body
Position Next;
/* data */
};
//清空整张链表
List makeEmpty(List L);
//判断链表是否为空
int isEmpty(List L);
int isLast(Position p, List L);
Position Find(void* x, List L);
void insert(int x, List L, Position P);
#endif /*_function_h*/
файл List.c
#include "function.h"
#include <stdio.h>
#include <stdlib.h>
List makeEmpty(List L) {
Position cur = L;
Position next;
while (cur!= NULL) {
next = cur->Next;
free(cur);
cur = next;
}
cur = NULL;
next = NULL;
//这里c是copy by value 所以改变那个指针,如果不赋值的话
//就是用void的话,不会将原来的指针改变。
L = NULL;
return L;
}
//right
int isEmpty(List L) {
return L->Next == NULL;
}
int isLast(Position P, List L) {
//判断P在不在List里
List cur = L;
while (cur->Next != P) {
cur = cur->Next;
}
if (cur == NULL) {
fprintf(stderr, "there is no P in the list L\n");
return -1;
}
if (P->Next == NULL) {
return 1;
}
else {
return 0;
}
return -1;
}
void insert(int x, List L, Position P) {
Position tmpCell;
tmpCell = (Position)malloc(sizeof(struct Node));
if (tmpCell == NULL) {
fprintf(stderr,"out of the space!\n");
}
tmpCell->element = x;
tmpCell->Next = P->Next;
P->Next = tmpCell;
}
но когда я запускаю код, я получаю сообщение об ошибке: неверный указатель кучи, так почему
и когда я пишу head->Next в качестве параметра в функции «makeEmpty», она может работать, но почему в моей программе «head» указывает на первую структуру, поэтому head->Next должен указывать на вторую структуру . Я действительно озадачен.
Я написал в формате книги «Структуры данных и анализ алгоритмов в c», спасибо за совет.
TL;DR: Попробуйте проследить за жизненным циклом вашей переменной head
.
Длинная версия:
Глава вашего списка — это указатель на локальную переменную main:
struct Node myNode = { 10,NULL };
List head = &myNode;
Тем не менее, вы пытаетесь освободить его:
makeEmpty(head);
При первом вводе функции makeEmpty()
cur
будет равна head
, а free(cur)
завершится ошибкой, поскольку head
— это адрес переменной в стеке, а не адрес, полученный с помощью malloc()
.
большое спасибо!!!!!!!!!!! хорошего дня. и я хочу использовать «牛逼», чтобы выразить свою благодарность
Указатель головы struct Node myNode = {10, NULL}
является переменной стека и не может быть передан free()
.
Одним из простых решений этой проблемы является создание функции для инициализации нового узла:
PtrToNode
create_node(int x)
{
PtrToNode tmp_node;
tmp_node = malloc(sizeof(struct Node));
if (tmp_node == NULL) {
fprintf(stderr,"out of the space!\n");
return NULL;
}
tmp_node->element = x;
tmp_node->Next = NULL;
return tmp_node;
}
После того, как вы сможете инициализировать свой список с новым узлом:
int
main(void) {
//initialize
List my_list = NULL;
my_list = create_node(10);
insert(20, my_list , my_list);
makeEmpty(my_list);
return 0;
}
большое спасибо!!!!!!!!!!! хорошего дня. и я хочу использовать «牛逼», чтобы выразить свою благодарность
Как указывают другие ответы, вы не можете free()
объекты, которые не были выделены malloc()
или аналогичными функциями.
Одним из ограничений функции insert
является то, что она не поддерживает вставку в начало списка. Это можно поддержать, изменив его так, чтобы он вставлялся в начало списка, когда P
равен NULL
. Также необходимо будет вернуть нового руководителя списка. Вот возможная реализация:
В функции.h:
List insert(int x, List L, Position P);
В списке.c:
List insert(int x, List L, Position P) {
Position tmpCell;
tmpCell = (Position)malloc(sizeof(struct Node));
if (tmpCell == NULL) {
fprintf(stderr,"out of the space!\n");
}
tmpCell->element = x;
if (P == NULL) {
tmpCell->Next = L;
L = tmpCell;
}
else {
tmpCell->Next = P->Next;
P->Next = tmpCell;
}
return L;
}
Переработанную функцию можно использовать для создания всех элементов списка…
В LinkedList.c:
#include <stdio.h>
#include "function.h"
int main(void) {
List head = insert(10, NULL, NULL); // insert to empty list
insert(20, head, head); // insert after first element of list
head = insert(0, head, NULL); // insert at beginning of list
makeEmpty(head);
return 0;
}
Вам действительно не следует прятать указатели за typedef. Это значительно усложняет чтение и поддержку кода и поэтому широко признается как плохая практика.