简体   繁体   English

在 C 中合并两个链表时遇到问题

[英]Trouble merging two linked lists in C

I am supposed to write a function to merge (put one at the end of another) two singly linked lists.我应该编写一个函数来合并(将一个放在另一个的末尾)两个单链表。 The user inputs a series of numbers into the console, for example: 1 2 3 4 0 (0 signifies the end of input and is not an element of the list).用户在控制台中输入一系列数字,例如:1 2 3 4 0(0 表示输入结束,不是列表的元素)。 These numbers are put into the linked list, the list now looks like this: 1 2 3 4. The process repeats again until we have two different linked lists.这些数字被放入链表,链表现在看起来像这样:1 2 3 4。这个过程再次重复,直到我们有两个不同的链表。 Then the merging function is called "void merge(struct Node head1, struct Node head2)".然后合并函数称为“void merge(struct Node head1, struct Node head2)”。 Programs ends after the new list is printed.打印新列表后程序结束。

My thought process would be to first have my pointer point at the end of the first list, then just make a while loop that will go through the other list and make the next element of the first list the current element of the second list.我的想法是首先让我的指针指向第一个列表的末尾,然后创建一个 while 循环,该循环将遍历另一个列表,并使第一个列表的下一个元素成为第二个列表的当前元素。

typedef struct Element Element;

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

Element *addNew(int data)
{
    Element *newN = (Element*)malloc(sizeof(Element));

    newN->data = data;
    newN->next = NULL;

    return newN;
}

Element *add_on_beginning(Element *head, Element *newN)
{
    newN->next = head;

    return newN;
}

Element *add_on_end(Element *head, Element *newN)
{
    if(head == NULL)
    {
        return newN;
    }

    Element *temp = head;

    while(temp->next != NULL)
    {
        temp = temp->next;
    }

    temp->next = newN;

    return head;
}

void printElement(Element *element)
{
    printf("%d ", element->data);
}

void printList(Element *head)
{
    Element *temp = head;

    while(temp != NULL)
    {
        printElement(temp);
        temp = temp->next;
    }
}

void merge(Element *head1, Element *head2)
{
    Element *temp1 = head1;
    Element *temp2 = head2;

    while(temp1->next != NULL)
    {
        temp1 = temp1->next;
    }

    while(temp2->next != NULL)
    {
        temp1->next = temp2;
        temp2 = temp2->next;
    }
}

int main()
{
    Element *head1 = NULL;
    Element *head2 = NULL;

    int arr[1000];
    char temp1;
    char temp2;
    int i = 0;
    int j = 0;

    printf("Input the first set of elements: \n");

    while(temp1 != '\n')
    {
        scanf("%d%c", &arr[i], &temp1);

        if(arr[i] == 0)
        {
            break;
        }

        head1 = add_on_end(head1, addNew(arr[i]));

        i++;
    }

    printf("Input the second set of elements: \n");

    while(temp2 != '\n')
    {
        scanf("%d%c", &arr[j], &temp2);

        if(arr[j] == 0)
        {
            break;
        }

        head2 = add_on_end(head2, addNew(arr[j]));

        j++;
    }

    merge(head1, head2);

    printList(head1);

    return 0;
}

So for some reason, the function only reads last two elements of the second list.所以由于某种原因,该函数只读取第二个列表的最后两个元素。

INPUT:输入:

1 2 3 4 0
5 6 7 8 0

OUTPUT:输出:

1 2 3 4 7 8

The result I'm supposed to get is我应该得到的结果是

INPUT:输入:

1 2 3 4 0
5 6 7 8 0

OUTPUT:输出:

1 2 3 4 5 6 7 8

This function这个功能

void merge(Element *head1, Element *head2)
{
    Element *temp1 = head1;
    Element *temp2 = head2;

    while(temp1->next != NULL)
    {
        temp1 = temp1->next;
    }

    while(temp2->next != NULL)
    {
        temp1->next = temp2;
        temp2 = temp2->next;
    }
}

is invalid.是无效的。

First of all it does not change the original pointers head1 and head2 because they are passed to the function by value.首先,它不会更改原始指针 head1 和 head2,因为它们是按值传递给函数的。 So the function deals with copies of the original pointers.因此该函数处理原始指针的副本。

Secondly in the function there is no check whether head1 or head2 is equal to NULL .其次在功能上没有检查是否head1head2等于NULL

The function can be defined the following way该函数可以通过以下方式定义

void merge( Element **head1, Element **head2 )
{
    if ( *head1 == NULL )
    {
        *head1 = *head2;
        *head2 = NULL;
    }
    else if ( *head2 != NULL )
    {
        while ( *head1 != NULL ) head1 = &( *head1 )->next;

        for ( ; *head2 != NULL; head2 = &( *head2 )->next )
        {
            *head1 = *head2;
            head1 = &( *head1 )->next;
        }
    }              
}

Pay attention to that there is no need to declare an array to input data in the list.注意不需要声明一个数组来输入列表中的数据。

Also these while loops还有这些while循环

    char temp1;
    char temp2;
    int i = 0;
    int j = 0;

    printf("Input the first set of elements: \n");

    while(temp1 != '\n')
    //..

and

   while(temp2 != '\n')
   //...

has undefined behavior because neither temp1 nor temp2 are initialized.有未定义的行为,因为temp1temp2都没有被初始化。

Think "code reuse".想想“代码重用”。 You've already written the functionality you want.您已经编写了所需的功能。 Reuse it...重复使用它...

printList( add_on_end( head1, head2 ) );

You've used malloc() to grab space for your nodes from the heap.您已经使用malloc()从堆中获取节点空间。 main() exits immediately, but it's good practice to at least acknowledge in a comment that you're not iteratively calling free() . main()立即退出,但最好至少在评论中确认您没有迭代调用free()

Edit printList() could be shifted into main() and its "final traversal" of the linked list used to make those calls to free() .编辑printList()可以转移到main()及其对链表的“最终遍历”,用于对free()进行这些调用。

One of your problems is:您的问题之一是:

while(temp2->next != NULL) {
    temp1->next = temp2;
    temp2 = temp2->next;
}

You are not updating the value of temp1.您没有更新 temp1 的值。

Also, why don't you just instead of this second while do:另外,你为什么不只是代替这一秒而做:

temp1->next = temp2;

I mean linked list 2 is properly linked, you just need to link the end of the first list with the beginning of the second.我的意思是链表 2 已正确链接,您只需要将第一个列表的末尾与第二个列表的开头链接起来。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM