将结构从一个列表的末尾移动到另一列表的开始

时间:2019-06-04 14:11:32

标签: c list pointers structure singly-linked-list

我正在尝试编写两个函数:一个函数推出列表的最后一个单元格,另一个函数使该单元格成为另一个列表的第一个单元格。不知何故,我的功能无法正常工作(我已经检查了代码的其他部分很多次了。)

void last_cell_out(CellPtr list, CellPtr c)
{
    if (list==NULL)/*if list is empty*/
        return;/*doing nothing*/
    if (list->next==NULL)/*if theres only one cell in the list*/
    {
        c=list;
        list=NULL;
        return;/*deleting from list and moving to c*/
    }
    if (list->next->next==NULL)
    {
        c=list->next;
        list->next=NULL;
    }
    else
        last_cell_out(list->next, c);
    return;
}

CellPtr new_first_cell(CellPtr list, CellPtr c)
{
    c->next=list;
    return c;/*returnes the start of the list*/
}

2 个答案:

答案 0 :(得分:1)

鉴于您如何描述需求,此功能对我来说似乎非常好

delegate_to

但是da_march_to_june = da.sel(time = slice('2000-03-01', '2000-06-30')).sum(dim = 'time') da_july_to_november = da.sel(time = slice('2000-08-01', '2000-11-30')).sum(dim = 'time') 有一些问题。

首先,您不需要此代码块

CellPtr new_first_cell(CellPtr list, CellPtr c)
{
    c->next=list;
    return c;/*returnes the start of the list*/
}

无论如何,它将在下一个周期中处理。

话虽这么说,您的函数确实从列表中删除了最后一个元素。 它只是不会返回或以您可以看到的方式更改代码。

一个选择是返回最后一个单元格,而不是将其作为参数传递。

last_cell_out

第二个变体将c作为指针传递,因此您可以在代码内更改其内容。

if (list->next->next==NULL)
{
    c=list->next;
    list->next=NULL;
}

如果列表太大,您也可以完全避免递归,以避免可能的堆栈溢出。

CellPtr last_cell_out(CellPtr *listPtr)
{
    CellPtr list = *listPtr;
    if (list==NULL)/*if list is empty*/
        return NULL;/*doing nothing*/
    if (list->next==NULL)/*if theres only one cell in the list*/
    {
        *listPtr = NULL;
        return list;/*deleting from list and return*/
    }
    return last_cell_out(&(list->next));
}

完整的测试程序:

void last_cell_out(CellPtr *listPtr, CellPtr *c)
{
    CellPtr list = *listPtr;
    if (list==NULL)/*if list is empty*/
    {
        *c = NULL;
        return;/*doing nothing*/
    }
    if (list->next==NULL)/*if theres only one cell in the list*/
    {
        *c=list;
        *listPtr = NULL;
        return;/*deleting from list and moving to c*/
    }
    last_cell_out(&((*listPtr)->next), c);
    return;
}

答案 1 :(得分:1)

函数last_cell_out必须通过引用接受其参数,因为它会更改其原始值。否则,该函数将具有未定义的行为,因为例如该语句

list=NULL;

不会更改列表的原始值。只会更改其局部变量list,该变量被定义为具有原始列表vlaue副本的参数。

因此,至少应通过以下方式定义函数

void last_cell_out(CellPtr *list, CellPtr *c)
{
    if ( *list == NULL )/*if list is empty*/
    {
        *c = NULL;
        return;/*doing nothing*/
    }        
    else if ( ( *list )->next == NULL )/*if theres only one cell in the list*/
    {
        *c = *list;
        *list = NULL;
        return;/*deleting from list and moving to c*/
    }
    else if ( ( *list )->next->next == NULL )
    {
        *c = ( *list )->next;
        ( *list )->next = NULL;
        return;/*deleting from list and moving to c*/
    }
    else
    {
        last_cell_out( &( *list )->next, c );
        return;/*doing nothing*/
    }        
}

这是一个演示程序。

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

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

typedef struct Cell *CellPtr;

void last_cell_out(CellPtr *list, CellPtr *c)
{
    if ( *list == NULL )/*if list is empty*/
    {
        *c = NULL;
        return;/*doing nothing*/
    }        
    else if ( ( *list )->next == NULL )/*if theres only one cell in the list*/
    {
        *c = *list;
        *list = NULL;
        return;/*deleting from list and moving to c*/
    }
    else if ( ( *list )->next->next == NULL )
    {
        *c = ( *list )->next;
        ( *list )->next = NULL;
        return;/*deleting from list and moving to c*/
    }
    else
    {
        last_cell_out( &( *list )->next, c );
        return;/*doing nothing*/
    }        
}

CellPtr new_first_cell(CellPtr list, CellPtr c)
{
    c->next = list;
    return c;/*returnes the start of the list*/
}

void print_cells( CellPtr list )
{
    for ( CellPtr current = list; current != NULL; current = current->next )
    {
        printf( "%d -> ", current->data );
    }

    puts( "NULL" );
}

int main(void) 
{
    CellPtr list = NULL;

    CellPtr cell = malloc( sizeof( struct Cell ) );
    cell->data = 1;

    list = new_first_cell( list, cell );

    print_cells( list );

    last_cell_out( &list, &cell );

    CellPtr list1 = NULL;

    list1 = new_first_cell( list1, cell );

    print_cells( list );
    print_cells( list1 );

    last_cell_out( &list1, &cell );

    free( cell );

    return 0;
}

其输出为

1 -> NULL
NULL
1 -> NULL

考虑到将typedef用作指针是一个坏主意,因为它有时会使用户感到困惑。

函数last_cell_out可以更简单地编写而无需递归。例如

void last_cell_out(CellPtr *list, CellPtr *c)
{
    if ( *list )
    {
        while ( ( *list )->next ) list = &( *list )->next;
    }

    *c = *list;
    *list = NULL;
}

或递归

void last_cell_out(CellPtr *list, CellPtr *c)
{
    if ( *list && ( *list )->next )
    {
        last_cell_out( &( *list )->next, c );
    }
    else
    {
        *c = *list;
        *list = NULL;
    }       
}