【问题标题】:Merge linked lists合并链表
【发布时间】:2019-08-09 03:03:30
【问题描述】:

我正在尝试在 C++ 中合并两个链表而没有就位。但是每次创建的新列表在到达一个或另一个列表的 nullptr 后都会发出以下数字。

MyLinkedList mergeTwoLinkedList(MyLinkedList b) {
        MyLinkedList c;

        node *tempa = this->head;
        node *tempb = b.head;

        if (b.head == nullptr)
            return *this;

        if (this->head == nullptr)
            return b;

        if (tempa && tempb) {
            do
            {
                if ((tempa->val) <= (tempb->val)) {
                    c.addAtTail(tempa->val);
                    tempa = tempa->next;

                } else if ((tempa->val) >= (tempb->val)) {
                    c.addAtTail(tempb->val);
                    tempb = tempb->next;
                }
            }
            while (tempa && tempb);
            return c;
        }
}

【问题讨论】:

  • 不确定这是您的问题,但如果您的程序达到tempa &amp;&amp; tempb 并且这是错误的(尽管我认为由于您的其他 if 语句而这可能是不可能的),your program results in undefined behavior
  • return c; 应该移到最后一个 } 之前
  • But everytime the new list created emits out the following numbers after it reaches the nullptr 什么数字?
  • while (tempa &amp;&amp; tempb); 之后,您应该查看tempatempb 是否不为空,并将所有剩余节点添加到c
  • 玩具代码存在多个问题。除了上面发现的:addAtTail 是如何实现的?如果您添加到列表的实际末尾,则意味着您要添加到 tempatempb 的末尾。

标签: c++ singly-linked-list


【解决方案1】:

这是一种非常常见的归并排序模式。让我首先通过删除冗余测试来简化您的循环(因为如果值 A 不小于等于 B,那么根据定义它大于)。

while (tempa && tempb)
{
    if (tempa->val <= tempb->val) {
        c.addAtTail(tempa->val);
        tempa = tempa->next;
    } else {
        c.addAtTail(tempb->val);
        tempb = tempb->next;
    }
}

因此,将发生的情况是,只要任一列表到达末尾,您的循环就会结束并且不再添加任何值。

在我看来,这个问题最简单和最易读的解决方案是在之后再添加两个循环,它只是附加剩余的尾部:

for(; tempa; tempa = tempa->next)
{
    c.addAtTail(tempa->val);
}

for(; tempb; tempb = tempb->next)
{
    c.addAtTail(tempb->val);
}

通常会看到其他解决方案,其中主循环直到 两个 指针都为 NULL 时才会终止,但这需要在循环内进行更多测试,这可能会降低性能并肯定会降低可读性。

现在,如果您确实将其用于合并排序,您甚至不需要单独的列表。您可以通过修补列表节点将一个列表合并到另一个列表中。这使得添加整个尾部成为 O(1) 操作,这意味着在合并期间不会发生分配。如果合适的话,我会把它作为练习留给你。

【讨论】:

    【解决方案2】:

    假设addToTail() 定义正确。您显示的代码存在缺陷。 在循环中:

    do
    {
        if ((tempa->val) <= (tempb->val)) {
            c.addAtTail(tempa->val);
            tempa = tempa->next;
    
        } else if ((tempa->val) >= (tempb->val)) {
            c.addAtTail(tempb->val);
            tempb = tempb->next;
        }
    } while (tempa && tempb);
    

    while 条件正在检查 tempa &amp;&amp; tempb --> 您正在检查它们是否有效。可能存在一个列表比另一个列表具有更多节点的情况。在这种情况下,您将错过从其他列表中复制节点的机会。为了纠正这个缺陷,您可以按如下方式更改代码:

    MyLinkedList mergeTwoLinkedList(MyLinkedList b) {
        MyLinkedList c;
    
        node *tempa = this->head;
        node *tempb = b.head;
    
        if (b.head == nullptr)
            return *this;
    
        if (this->head == nullptr)
            return b;
    
        if (tempa && tempb) {
            do
            {
                if ((tempa->val) <= (tempb->val)) {
                    c.addAtTail(tempa->val);
                    tempa = tempa->next;
    
                } else if ((tempa->val) >= (tempb->val)) {
                    c.addAtTail(tempb->val);
                    tempb = tempb->next;
                }
            }
            while (tempa && tempb); /* here  one of the tempa or tempb list may still have some nodes to copy to 'c' list */
    
            if (tempa) { // checking whether tempa list has more nodes to cover
                while (tempa) {
                    c.addAtTail(tempa->val);
                    tempa = tempa->next;
                }
            } else if (tempb) { // checking whether tempb list has more nodes to cover
                while (tempb) {
                    c.addAtTail(tempb->val);
                    tempa = tempb->next;
                }
            }
        }
        return c;       // returning the new list after merging
    }
    

    这应该可以解决您的问题。希望这会有所帮助,谢谢:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-19
      • 2021-02-26
      • 2016-07-13
      • 2010-12-25
      • 2020-05-24
      相关资源
      最近更新 更多