简体   繁体   中英

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). 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. Then the merging function is called "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.

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. 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 .

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

    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.

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. main() exits immediately, but it's good practice to at least acknowledge in a comment that you're not iteratively calling free() .

Edit printList() could be shifted into main() and its "final traversal" of the linked list used to make those calls to free() .

One of your problems is:

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

You are not updating the value of 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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