我看到了这个节点删除功能,并将其与我的书进行了比较。它(几乎(完全不同,我想后者对学习有用......?但是我无法理解如果只需要向前移动指针,为什么甚至使用免费。也许我错过了什么。
作为参考,这是我书中的删除节点函数:
char delete(ListNodePtr *sPtr, char value){
if(value == (*sPtr)->data){
ListNodePtr tempPtr = *sPtr;
*sPtr = (*sPtr)->nextPtr;
free(tempPtr);
return value;
}
else{
ListNodePtr previousPtr = *sPtr;
ListNodePtr currentPtr = (*sPtr)->nextPtr;
while(currentPtr != NULL && currentPtr->data != value){
previousPtr = currentPtr;
currentPtr = currentPtr->nextPtr;
}
if(currentPtr != NULL){
ListNodePtr tempPtr = currentPtr;
previousPtr->nextPtr = currentPtr->nextPtr;
free(tempPtr);
return value;
}
}
return ' ';
}
我还尝试完全删除 temp 变量和 free 调用,并且该函数仍然(显然(有效,因为在打印函数中不打印"已删除"值。
一直在查看链表上的其他来源,其中许多都显示了免费功能的用法,奇怪。
Linus描述了Linux内核中使用的列表。有趣的是,这些是侵入性列表,这意味着列表管理代码不负责释放节点,因为列表不拥有它们。
此外,该站点上的代码不是用于删除节点的完整功能,而只是用于取消链接的行。
不过,您自己的列表可能是使用malloc()
-ed 内存的拥有列表,对吧?
对于初学者来说,代码非常非常糟糕。首先是有重复的代码。其次,功能过于复杂。
它可以写得更简单。例如
char delete( ListNodePtr *sPtr, char value )
{
while ( *sPtr != NULL && ( *sPtr )->data != value )
{
sPtr = &( *sPtr )->nextPtr;
}
char result = *sPtr == NULL ? ' ' : value;
if ( *sPtr != NULL )
{
ListNodePtr tempPtr = *sPtr;
*sPtr = ( *sPtr )->nextPtr;
free( tempPtr );
}
return result;
}
此外,将 typedef 用于指针也是一个坏主意,就像在您的程序中一样ListNodePtr
显然是这样的 typedef。例如,此类型说明符
const ListNodePtr
并不意味着ListNodePtr
类型的指针指向的数据是常量数据,并且不能更改。这意味着指针本身是常量。
考虑以下演示程序
#include <stdio.h>
typedef int * IntPtr;
int main(void)
{
int x = 10;
const IntPtr p = &x;
*p = 20;
printf( "x = %dn", x );
return 0;
}
它的输出是
x = 20
至于你的问题
在链表删除函数中,是否有必要使用 free to 删除节点?
然后,退出函数后,对已删除节点的引用将丢失,如果不删除节点,则只要节点是动态分配的,就会发生内存泄漏。
如果你不使用free,那么你会导致内存泄漏。如果您在不释放内存的情况下移动指针,则会导致内存泄漏。