2013-10-27 72 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