如何在 C 中将链接列表解连接为 3 个单独的链接列表?
Posted
技术标签:
【中文标题】如何在 C 中将链接列表解连接为 3 个单独的链接列表?【英文标题】:How can I de-concatenate a Linked List into 3 separate Link Lists in C? 【发布时间】:2021-07-08 09:49:49 【问题描述】:所以我对数据结构还很陌生,我刚刚被介绍给单链表。我现在的任务是:
-
将 3 个链接列表连接成一个链接列表
将大型链接列表解连接回 3x 链接列表。
我已经成功完成了第一步,我创建了 3 个单独的链接列表,然后将它们相互附加。但是我在去连接阶段遇到了一个小问题,我希望有人能解释我做错了什么。首先,这是我的代码...
#include <stdio.h>
#include <stdlib.h>
typedef struct node
int data;
struct node * next;
node;
node * createLL(int);
void displayLL(node * head);
node * concatenate(node * head1, node * head2, node * head3);
void deconcatenate(node * head1, node * head2, node * head3);
int main()
struct node * head1 = NULL;
struct node * head2 = NULL;
struct node * head3 = NULL;
printf("Creating #1 Link List.. \n");
head1 = createLL(5);
displayLL(head1);
printf("\nCreating #2 Link List .. \n");
head2 = createLL(5);
displayLL(head2);
printf("\nCreating #3 Link List .. \n");
head3 = createLL(5);
displayLL(head3);
printf("\nConcatenating the Three Link Lists");
head1 = concatenate(head1,head2,head3);
displayLL(head1);
printf("\nDe-Concatenating the Link List into 3 Link Lists");
deconcatenate(head1,head2,head3);
printf("\nList #1\n");
displayLL(head1);
printf("\nList #2\n");
displayLL(head2);
printf("\nList #3\n");
displayLL(head3);
void deconcatenate(node * head1, node * head2, node * head3)
struct node * temp1;
struct node * temp2;
struct node * temp3;
int i,j,k;
i = j = k = 0;
temp1 = head1;
while (i < 5)
temp1 = temp1->next;
i++;
head2 = temp1; // 6
temp1 = NULL;
temp2 = head2;
while (j < 5)
temp2 = temp2->next;
j++;
head3 = temp2;
temp2 = NULL;
temp3 = head3;
while (k < 5)
temp3 = temp3->next;
k++;
temp3 = NULL;
void displayLL(node * HEAD)
for(node * p = HEAD; p != NULL; p = p->next)
printf("%d->",p->data);
printf("\n");
node * concatenate(node * head1, node * head2, node * head3)
struct node * temp = head1;
while (temp->next != NULL)
temp = temp->next;
temp->next = head2;
while (temp->next != NULL)
temp = temp->next;
temp->next = head3;
return head1;
node * createLL(int n)
int i = 0;
struct node * head = NULL;
struct node * temp = NULL;
struct node * p = NULL;
for(i = 0; i < n; i++)
temp = (node*)malloc(sizeof(node));
printf("Enter data in Node #%d",i);
scanf("%d",&(temp->data));
temp->next = NULL;
if (head == NULL)
head = temp;
else
p = head;
while (p->next != NULL)
p = p->next;
p->next = temp;
return head;
这是输出
如您所见,在 De-Concatenation 之后,LinkList #1 只有“1”节点,而它应该有值 1 到 5 的节点。LinkList #2 的节点比它多应该有。它应该有值 6 到 10 的节点,但它有 6 到 15 的节点。链接列表 #3 是唯一具有准确节点值的节点。
那么我在 deconcatenate Function 中做错了什么?
【问题讨论】:
列表去串联的标准或条件是什么? 链接列表 (head1) 的长度为 15 个节点,我需要将其拆分为 3 个链接列表,每个链接列表有 5 个节点。就是这样。 【参考方案1】:在我看来,这个作业对于初学者来说太难了。
如果您要通过连接其他三个列表的节点来构建一个列表,则指向三个列表的头节点的指针应通过引用传递,因为这些列表将在函数 concatenate
内更改。
即调用函数后三个列表为空。
在 C 中,通过引用函数来传递对象意味着通过指向它的指针间接传递对象。在这种情况下,该函数将通过取消引用指向该对象的指针来直接访问该对象。
所以函数至少应该像这样声明
node * concatenate(node ** head1, node ** head2, node ** head3);
同样的考虑也适用于函数deconcatenate
。调用函数后,原始列表应该是空的,因为它的元素正在被移动到其他三个列表中。
也就是说函数至少应该声明为
void deconcatenate(node **source_head, node ** head1, node ** head2, node ** head3);
但是这些函数的参数太多了。由于这两个函数都处理指向头节点的三重指针,因此最好声明一个具有三个数据成员的结构,这些数据成员保持指向头节点的指针的指针,并使用此结构的对象作为函数的参数。
例如
typedef struct triple_lists
node **head1;
node **head2;
node **head3;
triple_lists;
和
node * concatenate( triple_lists triple );
void deconcatenate( node **head, triple_lists triple );
正如我正确理解的那样,函数deconcatenate
应将源列表拆分为三个其他列表,这样每个列表将包含源列表的相邻元素,并且源列表应分为三个或多或少相等零件。
如果是这样,那么方法可以是以下。您需要三个指向节点的指针,它们将指定三个列表中每个列表的结尾。第一个指针前进一次,第二个指针前进两次,第三个指针前进三次,直到源节点不被耗尽。
这是一个演示程序。
#include <stdio.h>
#include <stdlib.h>
typedef struct node
int data;
struct node *next;
node;
typedef struct triple_lists
node **head1;
node **head2;
node **head3;
triple_lists;
int append( node **head, int data )
node *new_node = malloc( sizeof( *new_node ) );
int success = new_node != NULL;
if ( success )
new_node->data = data;
new_node->next = NULL;
while ( *head ) head = &( *head )->next;
*head = new_node;
return success;
FILE * display( const node *head, FILE *fp )
for ( ; head != NULL; head = head->next )
fprintf( fp, "%d -> ", head->data );
fputs( "null", fp );
return fp;
node * concatenate( triple_lists triple )
node *head = NULL;
node **current = &head;
*current = *triple.head1;
*triple.head1 = NULL;
while ( *current != NULL ) current = &( *current )->next;
*current = *triple.head2;
*triple.head2 = NULL;
while ( *current != NULL ) current = &( *current )->next;
*current = *triple.head3;
*triple.head3 = NULL;
return head;
void deconcatenate( node **head, triple_lists triple )
*triple.head1 = *head;
*triple.head2 = *head;
*triple.head3 = *head;
triple_lists tails = head, head, head ;
while ( *tails.head3 != NULL )
for ( size_t i = 0; *tails.head1 != NULL && i < 1; i++ )
tails.head1 = &( *tails.head1 )->next;
for ( size_t i = 0; *tails.head2 != NULL && i < 2; i++ )
tails.head2 = &( *tails.head2 )->next;
for ( size_t i = 0; *tails.head3 != NULL && i < 3; i++ )
tails.head3 = &( *tails.head3 )->next;
*head = NULL;
*triple.head2 = *tails.head1;
*tails.head1 = NULL;
*triple.head3 = *tails.head2;
*tails.head2 = NULL;
int main(void)
node *head1 = NULL;
node *head2 = NULL;
node *head3 = NULL;
int i = 0;
while ( i < 10 )
append( &head1, i++ );
while ( i < 15 )
append( &head2, i++ );
while ( i < 18 )
append( &head3, i++ );
printf( "list1: " );
putc( '\n', display( head1, stdout ) );
printf( "list2: " );
putc( '\n', display( head2, stdout ) );
printf( "list3: " );
putc( '\n', display( head3, stdout ) );
putchar( '\n' );
triple_lists triple = &head1, &head2, &head3 ;
node *head0 = concatenate( triple );
printf( "list0: " );
putc( '\n', display( head0, stdout ) );
printf( "list1: " );
putc( '\n', display( head1, stdout ) );
printf( "list2: " );
putc( '\n', display( head2, stdout ) );
printf( "list3: " );
putc( '\n', display( head3, stdout ) );
putchar( '\n' );
deconcatenate( &head0, triple );
printf( "list0: " );
putc( '\n', display( head0, stdout ) );
printf( "list1: " );
putc( '\n', display( head1, stdout ) );
printf( "list2: " );
putc( '\n', display( head2, stdout ) );
printf( "list3: " );
putc( '\n', display( head3, stdout ) );
return 0;
程序输出是
list1: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
list2: 10 -> 11 -> 12 -> 13 -> 14 -> null
list3: 15 -> 16 -> 17 -> null
list0: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 -> 15 -> 16 -> 17 -> null
list1: null
list2: null
list3: null
list0: null
list1: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> null
list2: 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> null
list3: 12 -> 13 -> 14 -> 15 -> 16 -> 17 -> null
我没有花时间编写一个清除列表以释放所有已分配内存的函数。希望你自己能写出这样的函数。
【讨论】:
【参考方案2】:void deconcatenate()
中的 while 循环不应该是 less than
而不是 equal to
?此外,您不需要循环遍历最后一个列表,只需将最后一个元素的 next 指针设置为 NULL
,因为您在创建第一个链表时已经这样做了。
【讨论】:
是的,我将条件从 i == 5 替换为 i @VenoM 在您的 while 循环中,当 i == 4 并且代码运行后, temp1 指向第 6 个节点。因此,通过将 head2 分配给 temp1 的下一个节点,您实际上将 head2 分配为指向第 7 个节点。您现在可以只执行 head2 = temp1 或减少循环数,有很多方法可以做到这一点。正如我上面所说,您不需要遍历最后一个列表。 更新了原始帖子中的代码,但仍然没有提供所需的输出。输出为: Link #1: 1 to 15 Link #2: 6 to 15 Link #3: 11 to 15 @VenoM 这是因为您将 temp1 设置为 NULL 而 temp1 只是临时变量。您应该将第 5 个节点的next
设置为 NULL。然后,正确终止第 5 个节点末尾的第一个链表。以上是关于如何在 C 中将链接列表解连接为 3 个单独的链接列表?的主要内容,如果未能解决你的问题,请参考以下文章