Linked list에서 아래 부문의 동작이 잘못되었다고 생각이 드네요.
https://dojang.io/mod/page/view.php?id=647
while (curr != NULL) // 포인터가 NULL이 아닐 때 계속 반복 { struct NODE *next = curr->next; // 현재 노드의 다음 노드 주소를 임시로 저장 free(curr); // 현재 노드 메모리 해제 curr = next; // 포인터에 다음 노드의 주소 저장 }
Visual Studio의 기능 중 Debug 를 통해 내부적인 흐름을 관찰하였는데, 위의 부문에서 의도하는 동작을 하지 않았습니다. 자세한 내용은 아래 압축 File에서 result 1, 2를 참고해주세요.
본래라면 result 3, 4, 5처럼 되야 정상인데, 반복문이 의미없이 동작합니다. (직접 Debug를 해보시길 바랍니다.) Linked list 특성상 이전 Node를 경유할 수 없습니다. 때문에 매번 마지막 Node를 찾아 제거하거나 아래 Algorithm과 같이 원하는 위치의 Node를 찾아 제거하는 방법으로 해야 합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | struct List_Node_Type* Pointer_Node = NULL; Pointer_Node = (struct List_Node_Type*) &Pointer_List->Header_Node; int index = 0; for (index = 0; index < position; index++) { Pointer_Node = (struct List_Node_Type*)Pointer_Node->Pointer_Link; } struct List_Node_Type* Pointer_Delete_Node = NULL; Pointer_Delete_Node = (struct List_Node_Type*) Pointer_Node->Pointer_Link; Pointer_Node->Pointer_Link = (struct List_Node_Type*)Pointer_Delete_Node->Pointer_Link; free((struct List_Node_Type*)Pointer_Delete_Node); | cs |
가장 상단의 Algorithm은 첫 번째 Node를 제거하고 다음 Node를 제거하는 방식으로 의도됩니다. 하지만 첫 Node를 제거하는 순간 다음 노드의 접점은 사라지게 됩니다 .따라서 가장 선두의 Node만 Memory 해제될 뿐 그 후의 Node는 제거되지 않습니다.
이상진의 자료구조 책을 참고하여 제가 따로 Linked list를 만든 Blog가 있습니다.
https://breakinformation-byr.blogspot.com/2019/09/linked-list-alpha.html
한번 비교해보시기 바랍니다. 감사합니다.
예제 코드의 동작은 잘못되지 않았고, C 언어에서 전형적으로 작성하는 코드입니다.
블로그의 링크한 것처럼 remove 동작이 복잡하게 작성될 이유는 없습니다.
예제 코드를 보면 처음에 3개의 노드를 추가하고, 각각의 값은 10, 20, 30입니다. 스택 프레임으로 보면 알 수 있습니다.
예제에서 마지막에 추가한 노드 30을 삭제합니다. 삭제한 이후는 다음과 같습니다.
이후에 문의한 while 반복문에서 나머지 노드를 삭제합니다.
우선 반복문에서 노드 하나를 삭제한 모습입니다. data가 20인 노드가 삭제되었습니다.
free(curr)을 한 직후이므로 왼쪽 main 스택에서 curr은 어떤 것도 가리키지 않게 됩니다. 쓰레기 값이 들어가 있으므로 여기서는 똥 아이콘으로 표시하고 있습니다.
while 반복문의 마지막 코드인 curr = next를 실행한 결과입니다. curr이 쓰레기 값에서 연결 리스트의 노드를 가리키는 것으로 표시됩니다.
모든 노드를 삭제한 이후에는 다음과 같이 됩니다.
마지막 head 노드를 free로 메모리를 해제하면 완전히 사라집니다.
addFirst는 head 노드 뒤에 새 노드를 추가하고 있습니다.
head -> 10
에서 새 노드 20을 head 노드 뒤에 추가하면
head -> 20 -> 10이 됩니다.
스택 프레임에서는 20 노드가 가장 아래에 그려지고, head는 가장 아래에 있는 20 노드를 가리키게 됩니다.
메모리를 해제했을 때 다음 노드의 접점이 사라지지 않게 하기 위해
*next = curr -> next;에서 먼저 다음 노드 위치를 저장하고,
free(curr)로 현재 노드를 해제하고
curr = next;로 다음 노드의 위치를 저장합니다.
메모리 해제 동작에도 문제는 없습니다.
C 언어 스택 프레임 시각화로 동작을 하나씩 살펴보기 바랍니다.
다시 분석해보니 제가 틀렸네요 ㅎㅎ;; (예전에 공부를 했었는데, 갑자기 다시 보니까 이상해서 올렸습니다.)
저는 head node를 끊고 메모리 해지하는 것이 문제라고 생각했는데, 저의 고정관념을 부숴버리는 코드였네요. head node와 그 이후의 node를 서로 분리하여 각각 memory를 해제하는 방식이 새롭네요. 제 코드에도 적용시켜 봐야겠습니다. ㅎㅎ