2013-10-27 71 views
0

我有一个链接列表的合并实现。它接受两个类型为List的参数,它是一个包含Node* head指针的类和包含typename T dataNode* next的结构Node。我遇到的问题是我的实现没有按照它应该的方式链接节点,或者我只是在错误地解决问题。它需要做的是,如果你做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; 
     } 
    } 
} 
} 

将包含在该节点是已为我们提供了一个类类型,它包含了所有正确的重载运算符,我们需要的数据。整个代码运行得很好,直到主要超出范围,然后析构函数被调用以获得剩余内容,之后我得到一个Debug Assertion Failed Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

我真的不知道如何去做这件事,我已经绘制了很多次,这一切似乎都对我有意义。如果任何人有任何提示让我朝正确的方向,我将不胜感激。感谢大家的期待!

+0

请检查你是不是删除两次的东西(如节点)。在进行合并时,您不会为list1创建新对象,因此您可能正在尝试删除list1,list2和list3。 – asalic

回答

1

预期这不起作用:

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

您需要检查,如果一个指针解引用它,否则你会得到不确定的行为之前NULL。 (这意味着任何事情都可能发生,非常糟糕。) 另外,您应该使用nullptr而不是NULL。

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

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

1

那么对于初学者有什么错在这里:

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

如果完成遍历列表1,那么你想要的是点列表1的最后一个节点,在列表2点。 list1Ptr = list2Ptr;
没有做到这一点。它只是改变局部变量的值。
同为这一部分:

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

这是一个不好的做事:
list1Ptr->data > list2Ptr->data && list1Ptr != NULL && list2Ptr != NULL
如果如果您尝试访问空值>数据有一定将是麻烦(因为list1Ptr成为NULL,则通常表达式将从左到右执行)。
另外:

 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 
+0

非常感谢,我肯定会为这些提示而努力! – floatfil

+0

做了一些改变,但它似乎仍然在做同样的事情,不管我改变了多少。我调试了一些cout,似乎这不是合并这两个列表,或将其他列表设置为合并列表。 – floatfil

+0

@floatfil好的,添加了伪代码,这可能会帮助你。 – digvijay91