xxnonamexx   2년 전

고수님들 도와주세요 ㅠㅠ

제 생각에는 맞다고 생각하는데 자꾸 '틀렸습니다'가 뜨는 이유가 짐작이 안갑니다 ㅠㅠ


코드 부연 설명이 필요하시다면 즉각즉각 달려와서 말씀드리겠습니다 ㅠㅠ

recoma   2년 전

22, 25라인에 그냥 pop()을 해버리면 heap균형이 깨지기 때문에 큐에 원소가 하나만 남아 있어도, max와 min 값이 다르게 출력 됩니다.

xxnonamexx   2년 전

혹시 heap의 균형이 깨진다는 말이 정확하게 무슨 말인지 여쭤봐도 될까요,,,?ㅠㅠ

힙은 알아낸지 얼마안되서 지식이 부족합니다 ㅠㅠ

recoma   2년 전

아까 댓글로 "pop()을 하면 heap의 균형이 깨진다" 라고 썼는데, 제가 잘못 설명했습니다. 나중에 공부하시는 데 오해의 소지가 있을 것 같아 이 부분은 그냥 무시하시는 게 좋을 것 같습니다. 깨진 다기 보다는 heap이 "고장난다"  표현이 나을 것 같네요.

아시다시피 heap의 구조는 대부분 이진 트리로 표현 합니다. 파이썬에서는 리스트를 heap처럼 쓸 수 있는데, 그 이유는 리스트의 정보를 이용해서 이진 트리로 표현하기 때문입니다.


예를 들어서 파이썬에서 최소 힙과 최대 힙에 8,9,5,3,7,1,7,3을 순서대로 삽입하면, 최소/최대 힙의 리스트 상태는 다음과 같이 나타납니다.

min_h: [1, 3, 3, 5, 7, 8, 7, 9]
max_h: [9, 8, 7, 3, 7, 1, 5, 3]


두 배열이 정렬되어 있지 않아 보여도 heapq모듈에서는 이 리스트를 이진 트리로 보고 수행하기 때문에 heappop()으로 차례대로 꺼내면 정렬된 상태로 출력이 됩니다.

그런데 이 리스트를 수동으로 조작을 하게 되면 힙의 결과가 정상적으로 출력 되지 않을 가능성이 높습니다. 예를 들어, min_h의 4번째 인덱스를 7에서 2로 수정하면 2가 3 뒤에 출력이 됩니다.
min_h = [1, 3, 3, 5, 2, 8, 7, 9]
출력 결과: 1 3 3 2 5 7 8 9

위에 올렸던 반례 에서 3 2 1 4 순으로 삽입을 하면 min_h, max_h는 다음과 같이 나타납니다

min_h: [1, 3, 2, 4]
max_h: [4, 3, 1, 2]

여기서 위의 코드 대로 "D 1"를 두 번 수행하면 아래와 같이 요소가 남습니다.

min_h: [1, 3]
max_h: [2, 1]

max_h 에서는 heappop() 으로 가장 값이 큰 것부터 꺼내서 2,1 만 남았지만, pop()을 사용한 min_h에서는 값 크기와 상관 없이 맨 뒤(2,4)를 꺼냈기 때문에 max_h와 min_h에서 저장된 요소들이 달라지게 됩니다.

heap을 이용해 리스트를 다루실 때, heapq모듈 만을 사용하시는 것을 권장 드립니다.

xxnonamexx   2년 전

와 감사합니다 어떤 말씀이 하고 싶으신지 바로 이해했습니다.

그러면 아예 다른방법을 생각해야할 것 같네요 ㅠㅠ

친절한 답변 정말정말 감사합니다!

댓글을 작성하려면 로그인해야 합니다.