将结构从一个列表的末尾移动到另一个列表的开头
moving struct from end of one list to start of another 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*/
}
考虑到您对要求的描述,这个功能对我来说似乎非常好
CellPtr new_first_cell(CellPtr list, CellPtr c)
{
c->next=list;
return c;/*returnes the start of the list*/
}
但是 last_cell_out
有一些问题。
首先你不需要这段代码
if (list->next->next==NULL)
{
c=list->next;
list->next=NULL;
}
反正下个周期处理。
话虽如此,您的函数确实会从列表中删除最后一个元素。
它只是不 return 它或以您可以看到的方式在您的代码中更改它。
一个选项是 return 最后一个单元格,而不是将其作为参数传递。
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));
}
第二个变体会将 c 作为指针传递,因此您可以在代码中更改它的内容。
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;
}
您还可以完全避免递归,以避免列表变得太大时可能出现的堆栈溢出。
CellPtr last_cell_out(CellPtr *listPtr)
{
CellPtr list = *listPtr;
if(list == NULL)
return NULL;
if(list->next == NULL) {
*listPtr = NULL;
return list;
}
while(list->next->next != NULL)
list = list->next;
CellPtr tmp = list->next;
list->next = NULL;
return tmp;
}
完整的测试程序:
#include <stdlib.h>
#include <stdio.h>
typedef struct cell *CellPtr;
typedef struct cell
{
int contents; /* contents of the cell */
CellPtr next; /* next cell in the list */
} Cell;
CellPtr last_cell_out(CellPtr *listPtr)
{
CellPtr list = *listPtr;
if(list == NULL)
return NULL;
if(list->next == NULL) {
*listPtr = NULL;
return list;
}
while(list->next->next != NULL)
list = list->next;
CellPtr tmp = list->next;
list->next = NULL;
return tmp;
}
CellPtr new_first_cell(CellPtr list, CellPtr c)
{
c->next=list;
return c;/*returnes the start of the list*/
}
void show_list(CellPtr list)
{
if(list == NULL) {
printf("\n");
return;
}
printf("%d ", list->contents);
show_list(list->next);
}
int main()
{
CellPtr list = NULL;
CellPtr out;
int i;
show_list(list);
CellPtr elem = malloc(sizeof(struct cell));
elem->contents = 0;
list = new_first_cell(list, elem);
show_list(list);
out = last_cell_out(&list);
show_list(list);
list = new_first_cell(list, out);
show_list(list);
for(i = 1; i < 5; ++i) {
CellPtr elem = malloc(sizeof(struct cell));
elem->contents = i;
list = new_first_cell(list, elem);
}
show_list(list);
out = last_cell_out(&list);
show_list(list);
list = new_first_cell(list, out);
show_list(list);
}
函数 last_cell_out
必须通过引用接受它的参数,因为它改变了它们的原始值。否则该函数将具有未定义的行为,因为例如这个语句
list=NULL;
不改变列表的原始值。它仅更改其定义为具有原始列表值副本的参数的局部变量list
。
所以函数至少要这样定义
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;
}
}
我正在尝试编写两个函数:一个用于推出列表的最后一个单元格,另一个用于使该单元格成为另一个列表中的第一个单元格。不知何故,我的功能不起作用(我已经多次检查代码的其他部分)。
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*/
}
考虑到您对要求的描述,这个功能对我来说似乎非常好
CellPtr new_first_cell(CellPtr list, CellPtr c)
{
c->next=list;
return c;/*returnes the start of the list*/
}
但是 last_cell_out
有一些问题。
首先你不需要这段代码
if (list->next->next==NULL)
{
c=list->next;
list->next=NULL;
}
反正下个周期处理。
话虽如此,您的函数确实会从列表中删除最后一个元素。 它只是不 return 它或以您可以看到的方式在您的代码中更改它。
一个选项是 return 最后一个单元格,而不是将其作为参数传递。
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));
}
第二个变体会将 c 作为指针传递,因此您可以在代码中更改它的内容。
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;
}
您还可以完全避免递归,以避免列表变得太大时可能出现的堆栈溢出。
CellPtr last_cell_out(CellPtr *listPtr)
{
CellPtr list = *listPtr;
if(list == NULL)
return NULL;
if(list->next == NULL) {
*listPtr = NULL;
return list;
}
while(list->next->next != NULL)
list = list->next;
CellPtr tmp = list->next;
list->next = NULL;
return tmp;
}
完整的测试程序:
#include <stdlib.h>
#include <stdio.h>
typedef struct cell *CellPtr;
typedef struct cell
{
int contents; /* contents of the cell */
CellPtr next; /* next cell in the list */
} Cell;
CellPtr last_cell_out(CellPtr *listPtr)
{
CellPtr list = *listPtr;
if(list == NULL)
return NULL;
if(list->next == NULL) {
*listPtr = NULL;
return list;
}
while(list->next->next != NULL)
list = list->next;
CellPtr tmp = list->next;
list->next = NULL;
return tmp;
}
CellPtr new_first_cell(CellPtr list, CellPtr c)
{
c->next=list;
return c;/*returnes the start of the list*/
}
void show_list(CellPtr list)
{
if(list == NULL) {
printf("\n");
return;
}
printf("%d ", list->contents);
show_list(list->next);
}
int main()
{
CellPtr list = NULL;
CellPtr out;
int i;
show_list(list);
CellPtr elem = malloc(sizeof(struct cell));
elem->contents = 0;
list = new_first_cell(list, elem);
show_list(list);
out = last_cell_out(&list);
show_list(list);
list = new_first_cell(list, out);
show_list(list);
for(i = 1; i < 5; ++i) {
CellPtr elem = malloc(sizeof(struct cell));
elem->contents = i;
list = new_first_cell(list, elem);
}
show_list(list);
out = last_cell_out(&list);
show_list(list);
list = new_first_cell(list, out);
show_list(list);
}
函数 last_cell_out
必须通过引用接受它的参数,因为它改变了它们的原始值。否则该函数将具有未定义的行为,因为例如这个语句
list=NULL;
不改变列表的原始值。它仅更改其定义为具有原始列表值副本的参数的局部变量list
。
所以函数至少要这样定义
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;
}
}