单一链接列表复制构造函数

时间:2016-10-05 06:49:46

标签: c++

不确定为什么节点仍然没有深度复制?头部和大小都很深的复制完美。

似乎NewNode-> Data和NewNode-> Next不是深度复制。不确定NewNode是否仍然指向That-> Data和That-> Next。

创建节点时是否需要传递实际值?

提前感谢您的回复。非常感谢。

传入的列表(SLList& that)。

Node是结构。节点不使用尾部。在我的案例中只有下一个和大小。

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;
}

3 个答案:

答案 0 :(得分:-1)

  1. 您应该创建一个新列表,其下一个指针应指向其节点,而不是原始列表的节点。
  2. 永远不要将变量命名为结构和类的成员。 它造成了混乱。
  3. 以下是更正后的代码。

    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;
    

答案 1 :(得分:-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需要指向其列表中的下一个节点。不幸的是,这个节点还不存在。因此,您必须先创建新节点或使用递归。

答案 2 :(得分:-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;

我们需要保持头部和尾部,因为尾巴会随着我们的进攻而移动,头部将保持不变并且是我们列表的头部。