중간에 낀 노드 삭제하기 — 5지 선다형. 초간단 딜리트 문제—링크드 리스트일 경우.

76.***.207.158

알겠습니다. 빌런 처럼 구는 사람들은 무시하겠습니다.

저도 1번이 확실한 답인건 알아요. 물론 널체크나 사소한것들이 있지만…근데 문제는 원글의 3번같은 경우인데….사실 1번의 경우처럼 포인터를 두개를 쓰지 않고, 1개만 쓰고도 삭제 타겟 노드를 리스트에서 링크를 끊어 고립시키는 목적을 이루어낼수는 있는데, 포인터 2개를 쓸때는 메모리 리크방지를 위해 메모리 삭제 delet temp; 쓰는 방법이 명확한데, 포인터를 1개만 쓰는 경우 노드의 메모리 삭제 delete 노드를 하는 경우가 생각대로 되지 않아요. 예를 들어 delete(node->next); 라는 문장이 일리걸한 것인지..논리적인 모순이 생기는건지….이건 아래 예제와도 연관이 있어요. 아래 예제에서도 포인터 1개만 이용하고서 메모리리크가 되지 않도록 고립된 노드메모리를 딜리트 해버려야 하는데…생각대로 되질 않네요.


 void deleteNode(Node* node) {
    if (node == nullptr) return;

    if (node->next == nullptr) { 
      // 노드가 한개던지, 마지막 노드일때?  일단 이 경우는 여기서는 고려하지 말자
    } else {
      node->data = node->next->data;
      node->next = node->next->next;   // 사실 여기까지는 아무문제 없어요. 그런데 여기까지만 보면 node 는 링크만 끊은것이지 메모리가 해제된건 아니어서 메모리 리크가 생기지 않나요? 그래서 아래처럼 딜리트까지 시켜야 할거 같은데 ...
      node = node->next;      // 노드 메모리삭제하기전에 포인터 이동
      delete node; // ????   포인터 1개만 쓰면서 노드메모리를 삭제할려면?  올드 노드가 필요한데...
    }
  }

아래는 테스트할 경우


#include <bits/stdc++.h>
using namespace std;

/* Link list node */
class Node {
public:
	int data;
	Node* next;
};

void push(Node** head_ref, int new_data)
{
	
	Node* new_node = new Node();
	new_node->data = new_data;
	new_node->next = (*head_ref);
	(*head_ref) = new_node;
}

void printList(Node* head)
{
	Node* temp = head;
	while (temp != NULL) {
		cout << temp->data << " ";
		temp = temp->next;
	}
}

 void deleteNode(Node* node) {
    if (node == nullptr) return;

    if (node->next == nullptr) { 
      // 노드가 한개던지, 마지막 노드일때?
    } else {
      node->data = node->next->data;
      node->next = node->next->next;
       node = node->next;      
      delete node; // ????  wrong
    }
  }

/* Driver code*/
int main()
{
	
	Node* head = NULL;

	// Use push() to construct below list 1->12->1->4->1 
	//push(&head, 1);
	//push(&head, 4);
	push(&head, 1);
	push(&head, 12);
	push(&head, 1);

	cout << "Before deleting \n";
	printList(head);

	//deleteNode(head);
    //deleteNode(head);
    deleteNode(head->next);
    

	cout << "\nAfter deleting \n";
	printList(head);
	return 0;
}

경우 1) 위의 테스트 경우 아웃풋
Before deleting
1 12 1
After deleting
1 1

경우 2) 그런데 아래처럼 메인함수를 테스트해보면
deleteNode(head);
deleteNode(head);
//deleteNode(head->next);

아웃풋이 아래처럼 나옵니다.


Before deleting 
1 12 1 
After deleting 
0 0 0 0 0 0.....

그런데
delete node;
를 코멘트해버리면
결과는 또 잘 나옵니다.

타겟 노드를 리스트에서 링크를 끊었으니 결과는 잘 나오는게 당연한데….문제는, 내 생각에 이 노드가 메모리 리크의 문제를 일으키지 않게 하기 위해 delete node; 를 해버려야 하는데…포인터를 1개만 쓰면서 그게 가능한지 모르겠어요. 포인터를 1개가 아니라 2개를 도입해서 원글의 1번의 경우처럼 쓰면, 이 문제는 없어지는데….포인터 1개만 쓰면서 원하는 노드 메모리를 딜리트 시키는 방법이 있는건지…. 그게 사실 원글의 3번에서 시도해보려했던 경우와 비슷한데….하긴 거기서도 더미 포인터를 도입했지만..