인프런 커뮤니티 질문&답변

태사단님의 프로필 이미지
태사단

작성한 질문수

[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part2: 자료구조와 알고리즘

연결 리스트 강의에서 Remove 함수 문의드립니다

작성

·

388

0

섹션1 - '연결 리스트 구현 연습' 강의에 대한 질문입니다.

위와 같이 Remove를 구현했습니다. (강의에서 head, tail에 해당하는 변수명은 first, last로 선언했습니다)

1) 삭제하려는 방이 첫 번째 요소인지와 이전 방이 null인지를 두 번 체크하는데, 그렇게 하지 않으면 예외가 발생하지 않는지 궁금합니다. (즉 위와 같이 if문을 작성하면 에러가 날 수 있나요?)

2) 삭제하려는 방을 따로 null처리할 필요는 없나요? room = null을 적어보니 사용되지 않는 코드처럼 회색으로 떠서요.

답변 4

1

Rookiss님의 프로필 이미지
Rookiss
지식공유자

그 부분은 무조건 처리를 해줘야 합니다.

이미 삭제된 방을 가리키고 있는 것도 자료구조 차원에서의 큰  문제이고,
추가로 메모리 측면에서도 문제가 됩니다.
C++과 다르게 C#는 메모리 해제를 직접하지 않고
아무도 해당 객쳋를 참조하지 않을 때 Garbage Collector라는 애가 알아서 메모리를 수거해갑니다.
그런데 누군가가 해당 객체를 참조하고 있으면, 해당 객체가 메모리에서 해제되지 않게 됩니다.

참고로 제가 작성한 코드를 유심히 보시면
room.Next.Prev = room.Prev 부분에서 말씀하신 부분의 처리를 간접적으로 해주고 있습니다.
왜냐하면 만약에 삭제할 대상이 첫번째 방이었다면, room.Prev가 null인 상태일테니,
결과적으로 room.Next.Prev = null로 밀어주기 때문이죠.

1

Rookiss님의 프로필 이미지
Rookiss
지식공유자

안녕하세요,
구현 방법이야 다양하니 동작만 하면 일단 장땡입니다.
그와는 별개로 보통 실수를 줄이려면 본인만의 스타일과 공식을 암암리에 만들면 좋은데,
기저사항 (매우 예외적인 케이스)을 가장 먼저 처리하는게 좋기 때문에 Head/Tail 비교가 두번 들어갔습니다.

아무튼 작성해주신 코드에서 수상한 부분이 몇몇 보이네요.
1) 일단 last, first는 갱신이 되지 않고 있는 것 같네요.
room은 어차피 삭제될 예정인데 굳이 room.prev = last를 해줄 필요가 없어 보입니다.
(last = room.prev를 의미하신건가요?)
2) 마지막 방이 아니라면 room.prev.next = room.next를 실행하는데,
하필 첫 방을 삭제했다면 room.prev.next에서 크래시가 나지 않을까요?
아니면 last, first 의미를 반대로 사용하고 계셨을 수도 있겠네요.

사실 눈으로 확인하는 것보다 가장 확실한 방법은 [처음] [마지막] [중간] 데이터를 한번씩 삭제해보는 것입니다.
정상적으로 다 되는지 테스트를 해보시면 보다 빠르게 버그 유무를 찾을 수 있을거에요.

그리고 두번째 질문으로 주신 [삭제하려는 방을 null 처리]하는 것은 아무 의미가 없습니다.
여기서 null 처리한다고 실제로 함수 호출한 밖에서도 null 처리가 되지 않기 때문이죠.
마치 임시 변수 Room<T> temp = room; 을 한 다음 temp = null 처리하고 room이 null 되길 기대한 셈이 됩니다.

0

태사단님의 프로필 이미지
태사단
질문자

아 맨 앞의 요소가 삭제될 때 두번째 방의 prev에 사실상 null을 대입하게 되는거군요. 그것도 모르고 null도 대입해보고 동적 배열에서 한거처럼 default도 해보고 뻘짓을... ㅋㅋㅋ

상세한 답변 정말 감사합니다!

0

태사단님의 프로필 이미지
태사단
질문자

감사합니다. 말씀하신 대로 first = room.next; 이 맞고, if문 내의 first와 last도 반대로 썼네요.

if (room != first) room.prev.next = room.next;

else first = room.next;

if (room != last) room.next.prev = room.prev;

else last = room.prev;

이렇게 수정하니 처음 가운데 끝 삭제 모두 에러 없이 동작하는 듯합니다.

한 가지 궁금한게 더 생겼는데요, 지우려는 방이 첫 번째 방이면 두 번째 방을 first로 지정하잖아요? 그런데 first에 해당하는 방이 여전히 prev값을 가지고 있는데, 이 부분은 그대로 두어도 되나요? 강의에서 구현하지는 않았지만 node.Previous 같은걸로 첫번째 방의 이전 값을 불러올 때 연결 리스트에서 제거된 값이 여전히 호출될 것 같아서요.

태사단님의 프로필 이미지
태사단

작성한 질문수

질문하기