合并两个排序的链表

Merge two sorted linked lists

本文关键字:排序 链表 两个 合并      更新时间:2023-10-16

我正在尝试合并两个排序的链表。在这里,我只是尝试实现我自己的算法。当然,互联网上给出了许多解决方案。代码是:

Node* MergeLists(Node *headA, Node* headB)
{
    int countA = 0, countB = 0;
    while(headA){countA++; headA = headA->next;}
    while(headB){countB++; headB = headB->next;}
    Node *res, *tres;
    res = new Node();
    res->next = NULL;
    tres = res;
    for(int i = 0; i < countA+countB-1; i++)
    {
        Node* temp = new Node();
        temp->next = NULL;
        tres->next = temp;
        tres = tres->next;
    }
    while(headA != NULL && headB != NULL)
    {
        if(headA->data > headB->data)
        {
            res->data = headB->data;
            res = res->next;
            headB = headB->next;
        }
        else if(headA->data < headB->data)
        {
            res->data = headA->data;
            res = res->next;
            headA = headA->next;
        }
    }
    while(headA)
    {
        res = headA;
    }
    while(headB)
    {
        res = headB;
    }
    return res;
}

这只是一个返回合并链表的头地址的函数。

考虑这个输入/输出示例:

Input (stdin):
3
4
1 3 5 6
3
2 4 7
1
15
1
12
0
2
1 2
My Output (stdout)
0 0 0 0 0 0 0
0 0
0 0
Expected Output
1 2 3 4 5 6 7
12 15
1 2

因此,我的输出打印全部为零。这是由于这段代码中的问题:

Node *res, *tres;
    res = new Node();
    res->next = NULL;
    tres = res;
    for(int i = 0; i < countA+countB-1; i++)// this is creating a new linked list.
    {
        Node* temp = new Node();
        temp->next = NULL;
        tres->next = temp;
        tres = tres->next;
    }

我认为 tres 和 res 之间的联系没有正确发生。你能告诉我如何纠正这个问题吗?

更新:

Node* MergeLists(Node *headA, Node* headB)
{
    int countA = 0, countB = 0;
    Node* tempA, *tempB;
    tempA = headA; tempB = headB;
    while(headA){countA++; tempA = tempA->next;}
    while(headB){countB++; tempB = tempB->next;}
    Node *res, *tres;
    res = new Node();
    res->next = NULL;
    tres = res;
    for(int i = 0; i < countA+countB-1; i++)
    {
        Node* temp = new Node();
        temp->next = NULL;
        tres->next = temp;
        tres = tres->next;
    }
    while(headA != NULL && headB != NULL)
    {
        if(headA->data > headB->data)
        {
            res->data = headB->data;
            res = res->next;
            headB = headB->next;
        }
        else if(headA->data < headB->data)
        {
            res->data = headA->data;
            res = res->next;
            headA = headA->next;
        }
    }
    if(headA)
    {
        res= headA;
        //res = res->next;
        //headA = headA->next;
    }
    if(headB)
    {
        res = headB;
        //res = res->next;
        //headB = headB->next;
    }
    return res;
}

这次~ no response on stdout ~

问题出在代码的这一部分。

while(headA){countA++; headA = headA->next;}
while(headB){countB++; headB = headB->next;}

执行此循环后,headA 和 headB 都指向 NULL;所以当

while(headA != NULL && headB != NULL)
循环

开始,它甚至不进入循环。由于此循环负责分配值,并且不会进入此循环。因此,所有值都设置为默认值 0。

正如@Slava提到的,你甚至不需要这个循环。由于您直接迭代节点,并且可以在发生 NULL 时停止。

创建一个临时指针,并使用该指针计算计数 A 和计数 B。

类似的东西

Node* temp;
temp = headA;
while(temp){countA++; temp = temp->next;}
temp = headB;
while(temp){countB++; temp = temp->next;}

此外,这可能会导致无限循环。请递增循环内的节点。或者只是将条件更改为 if,而不是 while。

    while(headA)
    {
        res = headA;
    }
    while(headB)
    {
        res = headB;
    }

更新-

另一个问题:在此计算后返回的 res,它指向最后一个元素。因此,输出将只是一个数字。

你能做的是

tres = res;
for(int i = 0; i < countA+countB-1; i++)
{
    ...
}
tres = res; // Add this line, so your keeping track of the original head
while(headA != NULL && headB != NULL)

最后return tres;而不是返回res;有了这个,您将返回原始头部。

你不需要计算元素,预先创建结果列表并使用这么多循环,在一个循环中完成所有操作:

Node* MergeLists(Node *headA, Node* headB)
{
    Node *res = nullptr;
    Node **ptr = &res;
    while( headA || headB  ) {
        Node *curr = new Node;
        curr->next = nullptr;
        *ptr = curr;
        ptr = &curr->next;
        if( headB == nullptr || ( headA && headA->data < headB->data ) ) {
            curr->data = headA->data;
            headA = headA->next;
        } else {
            curr->data = headB->data;
            headB = headB->next;
        }
    }
    return res;
}

注意:您不应该从函数返回原始指针 - 它很容易导致内存泄漏。您应该改用智能指针。

节点应该包含一些东西 - 您正在创建一个新节点并将其分配给链的末尾,但根本不在其中保存值,因此该值可能只是默认为零。

        res = res->next; <---
while(headA)
{
    res = headA;
}
while(headB)
{
    res = headB;
}
return res;

您返回的 res 是指向末尾而不是头部的指针。加 while(headB/headA) 假设在列表末尾添加提醒,但实际上会无限循环,因为指针没有增量。