【问题标题】:Delete from double Linked List从双向链表中删除
【发布时间】:2019-10-15 12:35:13
【问题描述】:

我正在尝试从双向链表中删除一个节点,但我遇到了问题 这个问题是当节点是第一个或中间它打印 0 而不是真正删除它,但是当它是列表中的最后一个节点时它工作得很好,这里是代码:

dList* del(dList*ptr, int x)
{

    dList *itr = NULL;
    for( itr = ptr; itr != NULL; itr = itr -> next)
    {
            // if the element is the first in the list
            if(itr -> value == x && itr -> prev == NULL)
            {
                itr -> next -> prev = NULL;
                ptr = itr -> next;
                free(itr);
            }
            // if the element is the last in the list
            else if(itr -> value == x && itr -> next == NULL)
            {
                itr -> prev -> next = NULL;

                free(itr);
            }
            // if its in the middle

            else if(itr -> value == x){
                    (itr -> prev) -> next = itr -> next;
                    (itr -> next) -> prev = itr -> prev;
                    free(itr);
            }
    }
    return ptr;
}

提前致谢!

【问题讨论】:

  • 是的,我的意思是,我会在 atm 编辑它
  • 我会尽力解决这个问题,非常感谢!

标签: c data-structures struct linked-list doubly-linked-list


【解决方案1】:

这个循环

for( itr = ptr; itr != NULL; itr = itr -> next)
{
        // if the element is the first in the list
        if(itr -> value == x && itr -> prev == NULL)
        {
            itr -> next -> prev = NULL;
            ptr = itr -> next;
            free(itr);
        }
        // ...

具有未定义的行为。

例如在for循环的第三个表达式中

itr = itr -> next

您正在使用已删除的指针

free(itr);

例如,如果列表只有一个节点,则itr->next 等于NULL。所以再次声明

itr -> next -> prev = NULL;

还调用未定义的行为。

如果通过指向它的指针通过引用传递头节点,函数看起来会简单得多。

还有一个更有用的返回值是列表中已删除节点的数量。

函数定义如下所示

size_t del( dList **ptr, int value )
{
    size_t n = 0;

    while ( *ptr != NULL )
    {
        if ( ( *ptr )->value == value )
        {
            dList *tmp = *ptr;
            *ptr = ( *ptr )->next;
            if ( *ptr ) ( *ptr )->prev = tmp->prev;

            free( tmp );
            ++n;
        }
        else
        {
            ptr = &( *ptr )->next;
        }
    }

    return n;
}

这是一个演示程序。

#include <stdio.h>
#include <stdlib.h>

typedef struct dList
{
    int value;
    struct dList *prev;
    struct dList *next;
} dList;


size_t del( dList **ptr, int value )
{
    size_t n = 0;

    while ( *ptr != NULL )
    {
        if ( ( *ptr )->value == value )
        {
            dList *tmp = *ptr;
            *ptr = ( *ptr )->next;
            if ( *ptr ) ( *ptr )->prev = tmp->prev;

            free( tmp );
            ++n;
        }
        else
        {
            ptr = &( *ptr )->next;
        }
    }

    return n;
}

int push_front( dList **head, int value )
{
    dList *new_node = malloc( sizeof( dList ) );
    int success = new_node != NULL;

    if ( success )
    {
        new_node->prev = NULL;
        new_node->value = value;
        new_node->next = *head;

        if ( *head ) ( *head )->prev = new_node;

        *head = new_node;
    }

    return success;
}

void out( dList *head )
{
    for ( ; head != NULL; head = head->next )
    {
        printf( "%d --> ", head->value );
    }

    puts( "NULL" );
}

int main(void) 
{
    dList *head = NULL;

    push_front( &head, 1 );
    push_front( &head, 2 );
    push_front( &head, 1 );

    out( head );

    size_t n = del( &head, 1 );

    printf( "%zu nodes are deleted.\n", n );
    out( head );

    n = del( &head, 2 );

    printf( "%zu nodes are deleted.\n", n );
    out( head );

    return 0;
}

它的输出是

1 --> 2 --> 1 --> NULL
2 nodes are deleted.
2 --> NULL
1 nodes are deleted.
NULL

【讨论】:

  • 我想你的意思是 ptr = itr -> 下一个?例如,如果 itr -> next 的地址是 300 并且我移动了指向它的 ptr “head”,而 itr 本身的地址是 200,所以我不再需要 itr?
  • 我只是在同一时刻意识到了这一点。对不起
猜你喜欢
  • 2018-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多