【问题标题】:Splitting list into two separate positive and negative lists将列表拆分为两个单独的正面和负面列表
【发布时间】:2021-03-27 08:54:40
【问题描述】:

我写了一个函数,将一个链表一分为二,其中传递的链表保存个数字并返回个数字列表。

struct elem {
    int val;
    struct elem *next;
};

struct elem *create(int val) {
    struct elem *temp;

    temp=(struct elem*) malloc(sizeof(struct elem));
    temp->val = val;
    temp->next = NULL;
    return temp;
}

void addToEnd(struct elem* list, int nval) {
    struct elem *temp = list;
    struct elem *new_list = create(nval);
    if(temp == NULL) {
        list = new_list;
        return;
    }
    while(temp->next != NULL) {
        temp = temp->next;
    }
    temp->next = new_list;
}


struct elem* split(struct elem** list) {
    struct elem* prev;
    struct elem* temp = *list;

    struct elem* positive = (struct elem*) malloc(sizeof(struct elem));
    struct elem* negative = (struct elem*) malloc(sizeof(struct elem));

    while(temp != NULL) {
        if(temp->val > 0) addToEnd(positive, temp->val);
        else if(temp->val < 0) addToEnd(negative, temp->val);
        prev = temp;
        temp = temp->next;
        free(prev);
    }

    *list = positive;
    return negative;
}

使用此函数后,我的两个列表都包含 0 作为第一个值,无论传递的列表在使用函数之前包含什么值。 如何解决这个问题?

【问题讨论】:

  • Kindle 粘贴整个代码
  • 因为 addToEnd 正是这样做的,所以将值添加到末尾。由于这是你在拆分中做的第一件事,它只会将元素添加到正数,而不对第一个元素做任何事情。
  • 如果列表为空,addToEnd 不起作用。它设置list = new_list,但listaddToEnd 的本地。要么将第一个参数声明为struct elem **list,要么返回更新后的list
  • 我认为应该可以。
  • @IanAbbott 谢谢,我决定 addToEnd 函数来创建新列表以防列表为空,但完全忘记了我写的只是在本地工作。修复了它,它可以按我的意愿工作。

标签: c split linked-list singly-linked-list function-definition


【解决方案1】:

函数addToEnd按值接受指向链表头节点的指针。

void addToEnd(struct elem* list, int nval) {
              ^^^^^^^^^^^^^^^^^   

即该函数处理指向头节点的指针值的副本。

所以在这个 if 语句中为参数的副本分配一个新值

if(temp == NULL) {
    list = new_list;
    return;
}

不改变原来指向头节点的指针。

你需要通过指向它的指针通过引用将指针传递给头节点。

在函数split 中分配内存,例如在这些声明中

struct elem* positive = (struct elem*) malloc(sizeof(struct elem));
struct elem* negative = (struct elem*) malloc(sizeof(struct elem));

或在这些陈述中

    if(temp->val > 0) addToEnd(positive, temp->val);
    else if(temp->val < 0) addToEnd(negative, temp->val)

没有意义,因为节点已经分配。您需要的是在新列表中移动具有负值的节点。

这是一个演示程序,展示了它是如何完成的。

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

struct elem 
{
    int val;
    struct elem *next;
};

struct elem * create( int val ) 
{
    struct elem *temp = malloc( sizeof( *temp ) );
    
    if ( temp != NULL )
    {
        temp->val  = val;
        temp->next = NULL;
    }
    
    return temp;
}

int addToEnd( struct elem **list, int val ) 
{
    struct elem *temp = create( val );
    int success = temp != NULL;
    
    if ( success )
    {
        while ( *list ) list = &( *list )->next;
        
        *list = temp;
    }

    return success;
}

struct elem*  split( struct elem **list )
{
    struct elem *new_list = NULL;
    struct elem **current = &new_list;
    
    while ( *list )
    {
        if ( ( *list )->val < 0 )
        {
            *current = *list;
            *list = ( *list )->next;
            ( *current )->next = NULL;
            current = &( *current )->next;
        }
        else
        {
            list = &( *list )->next;
        }
    }
    
    return new_list;
}

void display( const struct elem *list )
{
    for ( ; list != NULL; list = list->next )
    {
        printf( "%d -> ", list->val );
    }
    puts( "null" );
}

int main(void) 
{
    struct elem *list = NULL;
    
    const int N = 10;
    
    for ( int i = 0; i < N; i++ )
    {
        addToEnd( &list, i % 2 != 0 ? -i : i );
    }
    
    display( list );
    
    struct elem *new_list = split( &list );
    
    display( list );
    display( new_list );
    
    return 0;
}

程序输出是

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

【讨论】:

  • 您的意思是——“我已经为每个节点分配了两次——但它仍然无法工作??”
  • @DavidC.Rankin 我的意思是在函数拆分中不应分配新节点。:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-26
  • 1970-01-01
  • 1970-01-01
  • 2014-11-17
  • 2012-03-21
  • 2020-12-14
  • 2018-05-17
相关资源
最近更新 更多