将列表拆分为两个单独的正面和负面列表

Splitting list into two separate positive and negative lists

我写了一个将一个链表一分为二的函数,其中传递的列表保留 positive 数字和 returns negative 数字列表。

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 作为第一个值,无论传递的列表在使用函数之前包含什么值。 如何解决这个问题?

函数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