2016-10-05 49 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