반응형
https://www.acmicpc.net/problem/1927
문제
널리 잘 알려진 자료구조 중 최소 힙이 있다. 최소 힙을 이용하여 다음과 같은 연산을 지원하는 프로그램을 작성하시오.
- 배열에 자연수 x를 넣는다.
- 배열에서 가장 작은 값을 출력하고, 그 값을 배열에서 제거한다.
프로그램은 처음에 비어있는 배열에서 시작하게 된다.
입력
첫째 줄에 연산의 개수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 N개의 줄에는 연산에 대한 정보를 나타내는 정수 x가 주어진다. 만약 x가 자연수라면 배열에 x라는 값을 넣는(추가하는) 연산이고, x가 0이라면 배열에서 가장 작은 값을 출력하고 그 값을 배열에서 제거하는 경우이다. x는 231보다 작은 자연수 또는 0이고, 음의 정수는 입력으로 주어지지 않는다.
출력
입력에서 0이 주어진 횟수만큼 답을 출력한다. 만약 배열이 비어 있는 경우인데 가장 작은 값을 출력하라고 한 경우에는 0을 출력하면 된다.
예제 입력 1
9
0
12345678
1
2
0
0
0
0
32
예제 출력 1
0
1
2
12345678
0
1) 그림으로 알아보는 힙 자료구조 참고 사이트
<힙의 큰흐름 요약>
- 힙 자료구조 = 완전 이진 트리를 기초로 하는 자료구조
- 완전 이진트리 = 마지막을 제외한 모든 노드에서 자식들이 꽉 채워진 이진트리
- 힙 = 최대힙(Max heap) & 최소힙(Min Heap) 두가지가 존재
- 최대힙 : 부모노드의 값이 자식노드들의 값보다 항상 큼
- 최소힙 : 부모노드의 값이 자식노드의 값보다 항상 작음
- 항상 느슨한 정렬상태(반정렬 상태) 유지 : 부모-자식 간 (레벨 별) 정렬은 보장하고, 형제간의 정렬은 보장하지 않기 때문
- 중복값 허용
- 힙= 최댓값 또는 최솟값을 쉽게 뽑기 위한 자료구조
- 대체적으로 배열로 구현
- 완전이진트리를 기본으로 하기 때문에 비었는 공간이 없어 배열로 구현하기에 용이
- 루트노드 = 0번 index에 저장
- 각 노드를 기점으로
- 왼쪽 자식노드 =
- 오른쪽 자식노드 =
2) 자바의 최소힙 자료구조 ( PriorityQueue )
- 자바의 PriorityQueue는 우선순위 큐를 구현한 자료구조
- 요소들이 우선순위에 따라 정렬되어 저장
- 이 자료구조는 일반적으로 힙(Heap) 자료구조를 기반으로 하며, 기본적으로 최소 힙(min-heap)으로 구현되어 있음
- 즉, 가장 작은 값이 항상 큐의 맨 앞에 위치
①최소 힙의 삽입과정
- 트리의 가장 끝 위치에 데이터를 삽입
- 부모노드와 key값을 비교하여 작을 경우 부모 노드와 자리를 교체하는 것을 반복함
②최소 힙의 삭제과정
- 최상위 노드를 반환하며 삭제함
- 마치 Queue의 poll()와 같음
- 최상위 노드를 삭제한 후 최상위 노드에 가장 마지막 위치의 노드를 위치시킴
- 그 후, 삽입과 반대의 과정으로 자식노드와 비교하며 자리를 교체함
(좌, 우 노드와 비교하여 더 작은 값과 자리를 교체)
자바의 PriorityQueue의 기본 개념
- 우선순위 큐
- 각 요소는 우선순위를 가지며, 우선순위가 높은 요소가 먼저 처리
- 최소 힙
- 부모 노드의 값이 자식 노드의 값보다 작거나 같은 특성
- 따라서, 최상위 노드는 항상 가장 작은 값
자바의 PriorityQueue의 주요 메서드
- add(E e): 큐에 요소를 추가
- poll(): 가장 높은 우선순위를 가진 요소를 제거하고 반환
- peek(): 가장 높은 우선순위를 가진 요소를 반환하지만 제거하지는 않음
- isEmpty(): 큐가 비어 있는지 확인
3) 내가 구현한 코드
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PriorityQueue<Integer> pq = new PriorityQueue<>(); //최소힙
StringBuilder sb = new StringBuilder();
int N = Integer.parseInt(br.readLine());
for (int i = 0; i < N; i++) {
int num = Integer.parseInt(br.readLine());
//x가 0이라면 배열에서 가장 작은 값을 출력하고 그 값을 배열에서 제거
//만약 배열이 비어 있는 경우인데 가장 작은 값을 출력하라고 한 경우에는 0을 출력
if (num == 0){
sb.append(pq.isEmpty() ? 0 : pq.poll()).append("\n");
}else {//만약 x가 자연수라면 배열에 x라는 값 추가
pq.add(num);
}
}
System.out.println(sb.toString());
br.close();
}
}
4) 추가 문제
미들러 - 강의실
https://www.acmicpc.net/problem/1374
챌린저 - 소용돌이 이쁘게 출력하기
반응형