为什么我的 DeleteNode() 函数不工作?

Why isn't my DeleteNode() function working?

我创建了一个单向链表,其中 3 个节点的值分别为 45,90,100。我正在编写一个函数,它将删除列表的最后一个节点。但是输出打印了所有 3 个值。

void DeleteNode()
{
    struct node *ptr1=head,*ptr2=head;
        while(ptr1!=NULL&&ptr2->link!=NULL)

I have created two pointers ptr1 and ptr2 of struct node type for traversal. The loop is defined to run until ptr1 reaches last node and points to NULL and ptr2->link i.e. the last node points to NULL.

{
    ptr1=ptr1->link;
    ptr2=ptr2->link;
}
ptr2=NULL;

When the loop breaks, ptr2 will point to NULL and hence the last node should get deleted. But that doesn't happen.

}

“ptr2 将指向 NULL,因此最后一个节点应该被删除。”

没有。

你取消了一个局部变量的指针(在你取消它之前恰好指向 linked 列表中的某些东西),并且 not link linked 列表结构的指针部分:它对 linked 列表没有影响。

请注意,一旦更正此问题,您将发生内存泄漏(删除的节点)。

另外,ptr1 和 ptr2 总是指向同一个东西,保留两者是没有意义的。您最初可能有 ptr2==ptr1->link 或相反的想法,但这不是必需的,您的测试 ptr1 != NULL && ptr2->link != NULL 实际上等同于 ptr1 != NULL && ptr1->link != NULL.

ptr2是函数的局部变量。将其值设置为 NULL 不会更改列表节点的数据成员 link

此外,如果列表仅包含一个节点,则不会将其从列表中删除,因为全局变量 head 不会更改。

使用您的方法(您没有说明列表是如何创建的)函数可以如下所示

void DeleteNode( void )
{
    struct node *ptr1 = head;
    
    if ( ptr1 )
    {
        struct node *ptr2 = head->link;

        if ( ptr2 == NULL )
        {
            head = NULL;
        }
        else
        {
            while ( ptr2->link != NULL )
            {
                ptr1 = ptr1->link;
                ptr2 = ptr2->link;
            }

            ptr1->link = NULL;
        }
    }
}

这是一个演示程序。

#include <stdio.h>

struct node
{
    int data;
    struct node *link;
} *head;

void display( void )
{
    for ( struct node *current = head; current != NULL; current = current->link )
    {
        printf( "%d -> ", current->data );
    }
    puts( "null" );
}

void DeleteNode( void )
{
    struct node *ptr1 = head;
    
    if ( ptr1 )
    {
        struct node *ptr2 = head->link;

        if ( ptr2 == NULL )
        {
            head = NULL;
        }
        else
        {
            while ( ptr2->link != NULL )
            {
                ptr1 = ptr1->link;
                ptr2 = ptr2->link;
            }

            ptr1->link = NULL;
        }
    }
}

int main(void) 
{
    struct node n3 = { 100, NULL };
    struct node n2 = {  90, &n3  };
    struct node n1 = {  45, &n2  };
    
    head = &n1;
    
    display();
    
    DeleteNode();
    display();
    
    DeleteNode();
    display();

    DeleteNode();
    display();

    return 0;
}

程序输出为

45 -> 90 -> 100 -> null
45 -> 90 -> null
45 -> null
null

如果通过引用访问列表中的指针,函数可以定义得更简单。例如

void DeleteNode( void )
{
    struct node **current = &head;

    while ( *current && ( *current )->link )
    {
        current = &( *current )->link;
    }

    *current = NULL;
}

注意,如果是动态分配的,函数不会释放被删除的节点。在一般情况下,列表由动态分配的节点组成,DeleteNode 等函数应释放它们。