对于我的学术作业,我的任务是使用链表创建一个动态集 ADT。我的程序运行正常,但是当我尝试清除只有一个元素(尔格,单节点)的 Set 时,我的程序崩溃了。
以下是我的链表的定义方式:
typedef struct node{
int value;
struct node *next;
}Node;
typedef struct List{
Node *head;
Node *tail;
}*SetList;
以下是相关功能:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "List.h"
SetList ListCreate(){
SetList lptr;
lptr = malloc(sizeof(SetList));
lptr->head = NULL;
lptr->tail = NULL;
return lptr;
}
SetList ListAdd(SetList lptr, int x){
if(List_Is_Element_Of(x, lptr)){
puts("Value already exists, enter a unique value");
}
else{
Node *new = malloc(sizeof(Node));
new->value = x;
new->next = NULL;
if(lptr->head == NULL){
lptr->head = new;
lptr->tail = new;
}
else{
lptr->tail->next = new;
lptr->tail = new;
}
}
return lptr;
}
SetList ListRemove(SetList lptr, int x){
if(lptr == NULL){
puts("Memory Allocation Failed. Shutting down.");
exit(EXIT_FAILURE);
}
else if(!List_Is_Element_Of(x, lptr)){
puts("Value is not in set");
}
else if(lptr->head == NULL){
puts("Set is empty. Cannot remove that which does not exist");
}
else{
if(lptr->head->value == x){
Node *tempnode = malloc(sizeof(Node));
tempnode = lptr->head;
lptr->head = tempnode->next;
free(tempnode);
}
else{
Node *tempnode = malloc(sizeof(Node));
tempnode = lptr->head;
Node *tempnode2 = malloc(sizeof(Node));
tempnode2 = tempnode;
while(tempnode->value != x){
tempnode2 = tempnode;
tempnode = tempnode->next;
}
tempnode2->next = tempnode->next;
free(tempnode);
}
}
return lptr;
}
SetList ListClear(SetList lptr){
SetList templist = ListCreate();
templist = lptr;
while(templist->head!= NULL){
ListRemove(templist, templist->head->value);
templist->head = templist->head->next;
}
free(templist);
return lptr;
}
我在指针方面不是很有经验,所以我不完全确定问题来自哪里。删除存储了单个元素的列表是有效的,但清除它则不起作用。
提前感谢您的阅读。
你的 clear 函数不会改变 Tail,尽管你似乎没有使用 tail(除了你在添加节点时给它一个与 head 不同的节点?
当 clear 删除最后一个元素时,head 应为 null,因此在删除最后一个元素后取消引用它会很糟糕。
加上@NotLikeThat说的话。
没看错的话:
SetList ListClear(SetList lptr){
SetList templist = ListCreate(); // Create a new list
templist = lptr; // Immediately throw away the new list
// by overwriting the pointer with the old one
while(templist->head!= NULL){ // Delete everything from the old list
ListRemove(templist, templist->head->value);
templist->head = templist->head->next;
}
free(templist); // Free the old list
return lptr; // Return a pointer to freed memory
}
如果要通过删除所有元素来清除列表,则无需创建新列表,只需遍历现有列表,删除元素,直到它为空。该函数中真正需要的只是while
循环。
我认为ListRemove()
还应该检查它是否删除了最后一个元素并相应地更新tail
。