2014-12-24 6 views
-2

Qn) 단일 링크 된 목록에서 삭제할 노드에 대한 포인터 만 주어진 경우 을 삭제하는 방법은 무엇입니까? 링크 된 목록에서 삭제

나는 마지막 요소, 즉 1을 삭제하려고하지만 else 부분은 무한 루프 인쇄 쓰레기 값으로 간다.

Original link.

int main() 
{ 
    struct Node* head = NULL; 
    push(&head, 1); 
    push(&head, 4); 
    push(&head, 6); 
    push(&head, 8); 
    print(head); 
    del_p(head->next->next->next); 
    cout << endl; 
    print(head); 
    return 0; 
} 

void del_p(struct Node* current) 
{ 
    struct Node* temp; 
    if (current->next != NULL) 
    { 
     temp = current->next; 
     current->data = temp->data; 
     current->next = temp->next; 
     free(temp); 
    } 
    else 
    { 
     free(current); 
     current = NULL; 
    } 
} 
+1

그리고 자신의 디버깅 시도 중에 무엇을 발견 했습니까? –

+0

@MartinJames 가비지 값을 제공하지만 0x499602D2에 의해 지적 된대로 이제는 정상적으로 작동합니다. – Rooney10

답변

1

함수의 else 분기가 currentNULL에 재 할당하려고합니다. current로컬 복사본이 전달 되었기 때문에 문제가됩니다. 즉, 원래 포인터의 값을 수정할 수 없습니다.

메모리가 이미 할당 해제 된 노드에 액세스하고 있으므로 가비지를받는 이유입니다.

당신 하나가 바람직 더블 포인터, 또는 노드에 대한 참조가 필요합니다

void del_p(struct Node*& current) 
+0

0x499602D2 void del_p (struct Node * current)는 끝을 제외한 모든 값에 대해 정상적으로 작동합니다. 왜 그렇습니까? 그리고 참조를 사용하여 우리는 주소가 아닌 값으로 직접 작업합니다. 그래서 원래 포인터의이 문제를 어떻게 해결할 수 있습니까? U는 메모리가 이미 할당 해제 된 노드에 액세스하는 지점을 말했고 어디에서 할당을 해제 했습니까? Pls clarify – Rooney10

+0

@ Rooney10이 코드는'if' 브랜치 안에서 포인터 자체와 멤버를 수정하지 않기 때문에 참조를 사용하지 않을 때 모든 값을 처리하지만 끝납니다. 'else' 브랜치는 포인터의 * copy *를 변경시키는'current = NULL'을합니다. 포인터를 역 참조하는 것은 ('*'또는'->'와 함께) 참조를 반환하지만 현재는 참조가 아닙니다 (물론'&'를 사용하지 않는 한). 또한 메모리를 free()로 할당 해제했다. – 0x499602D2

0

삭제할 노드와 헤드 노드를 전달한 경우 노드가 삭제되기 전에 노드를 찾을 때까지 반복 할 수 있습니다. 그런 다음 이전 노드를 삭제할 노드가 가리키는 노드로 가리킨 다음 삭제할 노드를 해제 할 수 있습니다.

void delete(struct Node* to_delete, struct Node* head) 
{ 
    // check if node to be deleted is the head 
    if (to_delete == head) 
    { 
     head = to_delete->next; 
     return; 
    } 

    // make a local copy of the head just in case as to not alter it 
    struct Node* tempHead = head; 
    while(tempHead->next != to_delete) 
    { 
     tempHead = tempHead->next; 
    } 
    tempHead->next = to_delete->next; 
    free(to_delete); 
} 

면책 조항과 마찬가지로이 코드는 테스트하지 않았지만 개념 상 작동해야합니다.

+0

헤드 노드가 삭제 될 노드이면 작동하지 않습니다. – Adam27X

+0

참. 내가 편집 할게. –

0

다음 단계를 수행 할 연결리스트에 노드를 삭제하기위한 일반적인 알고리즘 :

  • 가져 오기 temp 포인터가 Head에서 시작되었습니다.
  • temp을 삭제하려는 노드로 이동하십시오 (이 경우 마지막 노드 : temp->next == NULL).
  • temp2의 메모리를 확보하십시오.
  • temp->next의 포인터를 NULL으로 설정하십시오.
  • head에 대한 포인터를 반환하십시오.

이제 이것이 유일한 알고리즘은 아니며,이를 수행 할 수있는 많은 방법이 있습니다. 당신은 좀 더 일반적인 통과하여 가능한 모든 노드를 삭제할 수 있도록이 코드를 만들 수 있습니다

void del_p(struct Node *head) 
{ 
    if (head != NULL) 
    { 
     struct Node *temp = head; 
     while (temp->next != NULL) temp = temp->next; 
     free(temp); 
    } 
} 

: (마지막 노드를 삭제하고자 할 경우) 다음 코드는 기능 del_p 내 해결책이 될 것입니다 이 당신을 위해 일하는

void del_p(struct Node **head, struct Node *delete_node) 
{ 
    if (head != NULL) 
    { 
     struct Node *temp = *head; 
     if (temp == delete_node) 
     { 
      *head = (*head)->next; 
      free(temp); 
     } 
     else 
     { 
      while (temp->next != NULL && temp->next != delete_node) 
       temp = temp->next; 
      if (temp->next != NULL && delete_node != NULL) 
      { 
       temp->next = delete_node->next; 
       free(delete_node); 
      } 
     } 
    } 
} 

희망,이 코드는 테스트되지 않은 상태입니다,하지만 당신은 문제가 있다면 말해 : 해당 노드에 대한 포인터 (또는 값)으로 보일 것이다 코드는 다음과!

+0

질문에 따르면 현재 포인터 만 사용할 수 있으므로 헤드를 사용하여 목록을 탐색 할 수는 없습니다. – Rooney10

+0

오, 알겠습니다. 그런 식으로 가장 쉬운 방법은 이중 포인터 매개 변수로 코드를 사용하는 것입니다. 이렇게하면 목록의 노드가 아닌 노드의 메모리가 수정되고 설정됩니다. NULL로 설정하십시오. – PatoBeltran

+1

"현재 쓰여져 있기 때문에 목록의 마지막 노드에 포인터를 건 경우에만 작동합니다." 사실, 그의 코드는 모든 노드에서 작동하지만 * 마지막으로 작동합니다. 그가 포인터에 대한 참조를 취하지 않았다는 사실은 노드를 목록에 보관했습니다. 또한 첫 번째 예제는 마지막 노드 만 삭제하고 (두 번째 노드가 의도 한 것이 맞는지는 확실하지 않음), 두 번째 예에서는'head = head-> next'가 목록에 영향을 미치지 않고'while' 루프에 영향을주지 않습니다. 'else' 브랜치는리스트에없는'delete_node'로부터 보호하지 않습니다 (따라서이 경우 무한 루프). – 0x499602D2

관련 문제