【问题标题】:Remove first node from a linked list and return it without allocating or deallocating memory.(C programming)从链表中删除第一个节点并返回它而不分配或释放内存。(C 编程)
【发布时间】:2020-06-24 00:06:12
【问题描述】:

我不允许释放内存或分配新内存(列表已为我分配)。所以本质上我正在尝试编写一个类似的函数,

struct node* returnAndRemoveFirstNode(struct node* head)
{
    struct node* returned = head;
    struct node* temp = head->next;
    returned->next = NULL;
    head = temp;
    return returned;
}

这不起作用,因为当我将返回的->next 设置为 null 时,我还将 head 的 next 设置为 null。我不知道如何解决这个问题,我相信有很多方法可以解决它,只是不知道如何解决。 对于 (1->2->3->4) 形式的列表,原始列表和返回的节点都类似于 (1->Null)

//Here is the node struct in case you need it
//I am not allowed to alter the struct..
struct node{
int data;
struct node *next;
};

【问题讨论】:

  • 您需要接收指向头指针的指针,以便在删除第一个节点时重新分配它。
  • @kronickrypt 删除所有满足条件的节点和删除第一个节点是两件不同的事情。看来您不需要返回已删除的节点。你需要的是释放被移除的节点。
  • 我只是用这个例子来分解问题,因为这是我没有得到正确的唯一情况。我不允许释放或分配新节点。
  • @wildplasser 谢谢你解决了我的问题。当我使用双指针修改我的解决方案时,当我需要更新双指针指向的指针时,我试图更新指向头指针的指针。

标签: c pointers linked-list dynamic-memory-allocation singly-linked-list


【解决方案1】:

我确定您没有正确理解原始任务。

不过,从列表中删除第一个节点并返回它的函数可以如下所示

struct node * returnAndRemoveFirstNode( struct node **head )
{
    struct node *returned = *head;

    if ( *head != NULL ) 
    {
        *head = ( *head )-next;
        returned->next = NULL;
    }

    return returned;
}

请注意,列表通常可以为空。所以指向头节点的指针可以等于NULL。

如果按照您评论中的描述进行操作

最初的任务是从列表中删除所有包含一个 特定数据并将所有这些节点添加到不同的列表中 退货。

那么函数可以如下面的演示程序所示。

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

struct node
{
    int data;
    struct node *next;
};

int push_front( struct node **head, int data )
{
    struct node *new_node = malloc( sizeof( struct node ) );
    int success = new_node != NULL;

    if ( success )
    {
        new_node->data = data;
        new_node->next = *head;
        *head = new_node;
    }

    return success;
}

void output( struct node *head )
{
    for ( ; head != NULL; head = head->next )
    {
        printf( "%d -> ", head->data );
    }

    puts( "null" );
}

struct node * remove_if( struct node **head, int cmp( int data ) )
{
    struct node *new_list = NULL;

    for ( struct node **current = &new_list; *head != NULL; )
    {
        if ( cmp( ( *head )->data ) )
        {
            *current = *head;
            *head = ( *head )->next;
            ( *current )->next = NULL;
            current = &( *current )->next;
        }
        else
        {
            head = &( *head )->next;
        }
    }

    return new_list;
}

int odd( int data )
{
    return data % 2 != 0;
}

int even( int data )
{
    return data % 2 == 0;
}

int main(void) 
{
    const int N = 10;

    struct node *head = NULL;

    for ( int i = N; i != 0; --i ) push_front( &head, i );

    output( head );

    putchar( '\n' );

    struct node *even_head = remove_if( &head, even );

    output( head );
    output( even_head );

    putchar( '\n' );

    struct node *odd_head = remove_if( &head, odd );

    output( head );
    output( odd_head );

    putchar( '\n' );

    return 0;
}

程序输出是

1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> null

1 -> 3 -> 5 -> 7 -> 9 -> null
2 -> 4 -> 6 -> 8 -> 10 -> null

null
1 -> 3 -> 5 -> 7 -> 9 -> null

【讨论】:

    【解决方案2】:
    struct node* returnFirstNode(struct node** head)
    {
        struct node* returned = *head;
        struct node* next = (*head)->next;
        *head = next;
        returned->next = NULL;
        return returned;
    }
    

    【讨论】:

    • 你在回答你自己的问题吗?
    • @JonathanWood 是的,我想出了解决方案。
    • @kronickrypt 解决方案不正确。看我的回答。而且我敢肯定你不理解最初的任务。
    • 是的,看起来不对。对于初学者,如果列表为空且head 为NULL,则使用head-&gt;next 和returned-&gt;next 将导致问题。另外,(*head)-&gt;next 是什么?我认为应该只是head-&gt;next。
    • @VladfromMoscow 最初的任务是从列表中删除包含特定数据的所有节点,并将所有这些节点添加到不同的列表中并返回它。我坚持的情况是删除第一个节点时。 Теперь понятно?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-07
    • 1970-01-01
    • 2019-01-07
    • 1970-01-01
    • 2019-09-10
    • 1970-01-01
    相关资源
    最近更新 更多