2016-10-05 232 views
0

不確定爲什麼節點仍然沒有深度複製?頭部和大小深得複製完美。單鏈接列表複製構造函數

似乎NewNode-> Data和NewNode-> Next不是深度複製。不知道NewNode是否仍然指向那個 - >數據和那 - >下一步。

創建節點時,是否需要傳遞實際值?

在此先感謝您的答覆。非常感激。

傳入的列表(SLList & that)。

節點是結構。節點不使用尾巴。只有下一個和我的情況大小。

Node* That = that.Head; 

//If not null then deep copy. 
if (That != nullptr) 
{ 
    Head = that.Head; 
    Size = that.Size; 

    //Interate through the list until the end nullptr 
    while (That != nullptr) 
    { 
     Node* NewNode = new Node; 

     NewNode->Data = That->Data; 
     NewNode->Next = That->Next; 
     That = That->Next; 
    } 
} 

//Set the head to null if list passed in is empty. 
else if (That == nullptr) 
{ 
    Head = nullptr; 
    Size = 0; 
} 
+0

是不是這樣,既然您創建while循環內的NewNode指針,你離開後,指針被刪除? – Foitn

+0

您可能想看到我更正的代碼。 – v78

+0

有人因爲不喜歡這個問題而連續低估每一個答案?我不喜歡代碼風格,但這不是一個不回答問題的理由 – CashCow

回答

-1

問題1:

Head = that.Head; 

Whups!兩個清單指向同一個頭。這不會很好結束。事實上,它徹底擊敗了鏈表的深層副本。

解決方案:

不要這樣做。

問題2:

while (That != nullptr) 
{ 
    Node* NewNode = new Node; 

    NewNode->Data = That->Data; 
    NewNode->Next = That->Next; 
    That = That->Next; 
} 

NewNode永遠不會保存任何地方外循環。這使得這個循環成爲丟失所有副本的內存泄漏生成器。

解決方案:

使該節點的副本,你現在做的,但第一個拷貝節點存儲在Head

問題3:

NewNode->Next = That->Next; 

副本指向列表上的一個節點被複制。

解決方案:

NewNode->Next需要指向其名單上的下一個節點。不幸的是,這個節點還不存在。所以你必須先創建新的節點或者使用遞歸。

+0

Ooo,好的,我明白你在說什麼,Node * NewNode正在脫離範圍。我需要將它存儲在Head中,以便在while循環結束後它不會超出範圍。因此一旦指針丟失就會泄漏內存。 –

-1
  1. 您應該創建一個新的列表,它的下一個指針應該指出其節點只不是原來的列表的節點。
  2. 永遠不要將您的變量命名爲您的結構和類的成員。 它造成混亂。

以下是更正後的代碼。

Node* That = that.Head; 

List new_list; 

//If not null then deep copy. 
if (That != nullptr) 
{ 
    new_list.Head=new Node; 
    new_list.Size = that.Size; 
    Node * head = new_list.Head; 

    //Interate through the list until the end nullptr 
    do{ 

     head->Data = That->Data; 
     That = That->Next; 
     if(That!=nullptr){ 
      auto tmp = new Node; 
      head->Next = tmp; 
      head = tmp; 
     } 
    }while(That!=nullptr); 

//Set the head to null if list passed in is empty. 
else if (That == nullptr) 
{ 
    new_list.Head = nullptr; 
    new_list.Size = 0; 
} 

return new_list; 
+0

我不喜歡你的解決方案中的一些東西:當它不是這樣的時候調用一個節點「頭」成爲尾巴),並做一段時間(1),當你可以使用一段時間的終止條件,甚至在這裏for循環。 – CashCow

+0

@CashCow提問者的確不是我給變量命名的人。 – v78

+1

@CashCow,你建議一個更好的條件。我選擇這種方法,我不想創建一個額外的節點。 – v78

-1

對於代碼中原始「新」調用的風格以及之後必須清理的問題,我所看到的一個明顯錯誤就是您忘記「鏈接」到「NewNode」並且而是鏈接到那個 - >下一個在你正在複製的列表中。

當你的列表單鏈表,你需要一個指針保持當前的「尾巴」,然後爲你創建一個新的節點,你把(使用你的風格)

Tail->Next = NewNode; 
NewNode->Data = That->Data; 
Tail = NewNode; 

你有什麼實際正在創建一個克隆數據的節點,但是鏈表不使用新節點,但仍使用舊節點。

因爲這是C++,你有一個構造函數,所以NewNode應該自動創建並使用nullptr作爲它的「Next」值,所以如果我們不進一步循環,我們可以假設這是設置的。

在現實中,我們也可以通過在我們需要構造函數中的數據,從而:

template< typename DataType > 
class SLNode 
{ 
public: 
     DataType Data; 
     SLNode<DataType> * Next; 

     SLNode() : Next(nullptr) 
     { 
     } 

     ~SLNode(); // exercise for you to implement 

     explicit SLNode(const DataType& data) 
      : Data(data), Next(nullptr) 
     { 
     } 
}; 

我做了一切公開,但您可能希望使數據成員私享使用getter和setter 。

反正現在你可以做以下的在循環....

while(That) 
{ 
    Tail->Next = new SLNode<DataType>(That->Data); 
    Tail = Tail->Next; 
    That = That->Next; 
} 

你的「頭」,在新的列表也是不正確的爲指向,從舊列表中的節點。不過,我們現在知道如何創建

Head = new SLNode<DataType>(that->Data); 
Tail = Head; 

我們需要保持頭和尾巴,我們尾遞歸會移動,頭部將停留在相同的,並且我們的名單之首。

+0

我開始認爲有人不希望這個問題得到解答。 – user4581301

+0

感謝您的回覆,絕對是一個很好的閱讀。對不起,如果我看起來像個白癡。對於C++來說,這是相當新的幾個月。我明天會明確地看看它,我要去睡覺了,上午3:50哈哈。 Rep ++。另外,我們不必爲實驗室實施尾部變量。 –

+0

尾部變量只在循環中。你不需要它在課堂上。您需要跟蹤輸入列表的尾部(您稱之爲)以及您正在編寫的列表的尾部。 – CashCow