将列表拆分为两个单独的正面和负面列表
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
我写了一个将一个链表一分为二的函数,其中传递的列表保留 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