Linked List合并两个列表,调试断言错误

时间:2013-10-27 17:57:47

标签: c++ pointers linked-list

我有一个链接列表的合并实现。它接受List类型的两个参数,它是一个包含Node* head指针和由Nodetypename T data组成的结构Node* next的类。我遇到的问题是我的实现不是应该连接节点,或者我可能只是错了。它需要做的是,如果你list1.merge(list2, list3);,那么list1将成为list2和list3节点的组合。我需要通过指针操作来执行此操作并且不需要新的内存分配,因此将修改list2和list3。这就是我现在所拥有的:

template <typename T>
void List<T>::merge(List& list1, List& list2) {

typename List<T>::Node* list1Ptr = list1.head;
typename List<T>::Node* list2Ptr = list2.head;

for(;;) {
    if (list1Ptr == NULL && list2Ptr != NULL) {
        list1Ptr = list2Ptr->next;
        head = list1.head;
        break;
    }
    else if (list2Ptr == NULL && list1Ptr != NULL) {
        list2Ptr = list1Ptr->next;
        head = list1.head;
        break;
    }
    else if (list1Ptr == NULL && list2Ptr == NULL) {
        head = list1.head;
        break;
    }
    else if (list1Ptr != NULL && list2Ptr != NULL) {

        if (list1Ptr->data > list2Ptr->data){
            typename List<T>::Node* temp;
            temp = list2Ptr->next;
            list1Ptr->next = list1Ptr;
            list2Ptr = temp;
        }
        else if (list1Ptr->data < list2Ptr->data) {
            typename List<T>::Node* temp;
            temp = list1Ptr->next;
            list1Ptr->next = list2Ptr;
            list1Ptr = temp;
        }
        else if (list1Ptr->data == list2Ptr->data) {
            list1Ptr = list1Ptr->next;
        }
    }
}
}

节点中包含的数据是为我们提供的类类型,它包含我们需要的所有正确的重载操作符。整个代码运行得很好,直到main超出范围,析构函数被调用剩下的东西,然后我得到一个Debug Assertion Failed Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

我真的不确定如何解决这个问题,我已经多次抽出它,这对我来说似乎都有意义。如果有人有任何提示让我朝着正确的方向前进,我将非常感激。谢谢大家的期待!

2 个答案:

答案 0 :(得分:1)

这不能按预期工作:

list1Ptr->data > list2Ptr->data && list1Ptr != NULL 
             && list2Ptr != NULL

在解除引用之前,您需要检查指针是否为NULL,否则您将获得未定义的行为。 (这意味着任何事情都可能发生,非常糟糕。) 此外,您应该使用nullptr而不是NULL。

然而,这不是错误消息的原因,因为您已检查其他条件中的所有NULL情况。

您的问题可能是建议的斜体。如果您想要评论,请告诉我们其余的代码。

答案 1 :(得分:1)

对于初学者来说,这里有些不对劲:

    if (list1Ptr == NULL && list2Ptr != NULL) {
        list1Ptr = list2Ptr;
        head = list1.head;
        break;
    }

如果你完成遍历list1,那么你想要的是将list1的最后一个节点指向list2。 list1Ptr = list2Ptr;
什么都不做。它只是改变局部变量的值 这一部分也是如此:

    else if (list2Ptr == NULL && list1Ptr != NULL) {
        list2Ptr = list1Ptr;
        head = list1.head;
        break;
    }

做事不好:
list1Ptr->data > list2Ptr->data && list1Ptr != NULL && list2Ptr != NULL
如果list1Ptr变为NULL,那么如果你试图访问NULL-&gt;数据肯定会有麻烦(因为通常表达式将从左到右执行)。
也:

        else if (list1Ptr->data > list2Ptr->data && list1Ptr != NULL 
             && list2Ptr != NULL) {
        typename List<T>::Node* temp = list2Ptr;
        list2Ptr = list2Ptr->next;
        temp->next = list1Ptr;
        }

这里也有一些问题。您首先将list2ptr存储在temp中。然后将list2ptr移动到list2中的下一个节点。但为什么要temp->next = list1ptr? 你应该重新思考这一部分。对于下一个其他区块也是如此 最好的。
编辑:
好吧,让我们看看还能做些什么:
这是我建议您使用的伪代码:

func(list1,list2):
ptr1 = list1.head
ptr2 = list2.head
declare pointer curr
if(ptr1!= NULL and ptr2!=NULL){
    if(ptr1->data < prt2->data)
    {curr = ptr1
    ptr1 = ptr1->next
    head = curr
    }
    else{
    curr = ptr2
    ptr1 = ptr2->next
    head = curr}}
else{
    head = whichever one is not NULL, or NULL if both of them are and return
    }
while(ptr1 != NULL and ptr2!=NULL){
    if(ptr1->data < ptr2->data){
    curr->next = ptr1
    curr = ptr1
    ptr1 = ptr1->next
    continue}
    else{
    curr->next = ptr2
    curr = ptr2
    ptr2 = ptr2->next
    continue}
}
if(ptr1 == NULL)
    curr->next = ptr2
else
    curr->next = ptr1