2016-10-05 4 views
0

노드가 아직 완전 복사가 아닌 이유를 잘 모르시겠습니까? 머리와 크기는 완벽하게 잘 복사됩니다.단일 링크 목록 복사 생성자

NewNode-> Data와 NewNode-> Next는 모두 딥 복사가 아닙니다. NewNode가 여전히 That-> Data and That-> Next를 가리키고 있는지 확실하지 않습니다.

노드를 만들 때 실제 값을 전달해야합니까?

미리 답변 해 주셔서 감사합니다. 매우 감사.

목록이 전달됩니다 (SLList &).

노드는 구조체입니다. 노드는 꼬리를 사용하지 않습니다. 내 경우에는 다음과 크기 만.

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

누군가 질문에 싫어하기 때문에 모든 대답을 순차적으로 downvoting합니까? 나는 코드 스타일을 좋아하지 않는다. 그러나 그 질문에 대답하지 않는 이유가 아니다. – 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

우우, 네가 말하는대로 Node * NewNode가 범위를 벗어났다. 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

나는 당신의 솔루션에서 싫어하는 몇 가지 : 노드가 "head"라고 부를 때 (처음에는 그렇지만 꼬리가 됨) 그리고 while (1)을 사용하면 잠시 동안 종료 조건이나 for 루프를 사용할 수 있습니다. – CashCow

+0

@CashCow 변수를 명명하지 않은 사람은 질문자가했습니다. – v78

+1

@CashCow, 당신은 더 좋은 조건을 제안합니다. 나는 그 방법을 선택했다. 나는 여분의 노드를 하나 만들고 싶지 않았다. – v78

-1

코드에서 원시 "새로운"호출의 스타일에 대해 말하고 나중에 정리해야 할 필요가 많은 명백한 버그는 "NewNode"에 "연결"하고 대신 당신이 복사하고있는 목록에있는 That-> Next를 연결하고 있습니다.목록은 단일 연결되기 때문에 당신이, 당신은 당신이 실제로 무엇

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

내가 만든 모든 공공 있지만 데이터 멤버가 비공개로하고자하는 사용 게터와 세터를 가질 수있다 :

현실에서, 우리는 또한, 따라서, 우리는 생성자에 필요한 데이터를 전달할 수 있습니다 .

어쨌든, 지금 당신은 그 이전 목록에서 노드를 가리키는으로 새 목록에
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 LOL입니다. Rep ++. 또한 실험실에 꼬리 변수를 구현할 필요도 없었습니다. –

+0

꼬리 변수는 루프에만 있습니다. 수업 시간에 필요하지 않습니다. 당신은 입력 목록 (당신은 그것을 부름)의 꼬리와 쓰고있는 꼬리표를 추적해야합니다. – CashCow