[백준] 11279 최대 힙 (C++)

조혜정·2021년 8월 12일
1

백준알고리즘

목록 보기
7/20
post-thumbnail

백준 11279 최대 힙 문제
백준 11279 최대 힙 소스코드

📄 문제 설명

Problem

널리 잘 알려진 자료구조 중 최대 힙이 있다.
최대 힙을 이용하여 다음과 같은 연산을 지원하는 프로그램을 작성하시오.

배열에 자연수 x를 넣는다.
배열에서 가장 큰 값을 출력하고, 그 값을 배열에서 제거한다.
프로그램은 처음에 비어있는 배열에서 시작하게 된다.

Input

첫째 줄 : 연산의 개수 N(1 ≤ N ≤ 100,000)
다음 N개의 줄 : 연산에 대한 정보를 나타내는 정수 x

만약 x가 자연수라면 배열에 x라는 값을 넣는(추가하는) 연산
x가 0이라면 배열에서 가장 큰 값을 출력하고 그 값을 배열에서 제거하는 경우이다.
입력되는 자연수는 2^31보다 작다.

Output

입력에서 0이 주어진 회수만큼 답을 출력한다.
만약 배열이 비어 있는 경우인데 가장 큰 값을 출력하라고 한 경우에는 0을 출력하면 된다.

Example Input

13
0
1
2
0
0
3
2
1
0
0
0
0
0

Example Output

0
2
1
3
2
1
0
0

📝 문제 해설

이 문제는 최대 힙을 구현하는 문제이다.
▶ 힙 (Heap)
힙은 ✔<완전 이진트리> 형태의 자료구조로 < 조건(Heap Condition)>을 만족한다.
주로 일차원 배열로 구현되며, 일반적으로 그룹을 정렬(Heap Sort)하거나,
입력된 데이터 안에서 <최소/최대 값>을 찾을 때 사용한다.
데이터의 삽입과 삭제가 빠르며 수행시간이 O(log N)이다.
✔ 이진 트리(Binary Tree) : 트리의 차수가 2이하인 트리
✔ 정 이진 트리(Full Binary Tree) : 모든 노드의 차수가 0 또는 2인 이진 트리
✔ 포화 이진 트리 (Perfect Binary Tree): 정 이진 트리에서모든 단말 노드의 깊이가 같은 이진 트리
✔ 완전 이진 트리 (Complete Binary Tree): 마지막 레벨은 노드가 왼쪽에 몰려있고 마지막 레벨을 제외하면 포화 이진 트리 구조를 띄고 있는 이진 트리.
▶ 최소 힙 (Min Heap)
최소 힙은 "부모노드의 키 값이 자식 노드의 키 값보다 항상 작다"는 힙조건을 가지고 있다.
부모노드의 키 값이 자식노드의 키 값보다 작은 관계가 유지되므로 트리 내에서 가장 작은 값은
항상 root 노드가 된다.
최대 힙의 삽입
최소 힙에 새로운 값(x)을 삽입할 때
ⓐ 가장 마지막 노드로 삽입한다.
ⓑ x가 부모 노드보다 클 때 부모 노드와 SWAP (반복)
ⓒ x가 부모 노드보다 작게되면 그 자리가 x의 자리가 된다.
최대 힙의 삭제
최소 힙에서 값을 삭제할 때
ⓐ root 노드를 삭제한다.
ⓑ root 노드에 마지막 노드를 삽입한다.
ⓒ 그 노드가 자식 노드보다 값이 더 작다면 (왼쪽 오른쪽 자식 중) 더 큰 값과 SWAP (반복)

</> Source Code

#include <bits/stdc++.h>

using namespace std;

int n;
vector<long> heap;

void pop(){
	if(heap.size() > 1){
		printf("%d\n", heap[1]);
		
		int node = 1, lastIdx = heap.size() - 1;
		heap[node] = heap[lastIdx];
		heap.erase(heap.begin() + lastIdx);
		
		while(true){
			int left = node * 2, right = node * 2 + 1;
			if(left >= lastIdx) break;
			
			int maxV = heap[left], maxPos = left;
			
			if(right < lastIdx && maxV < heap[right]){
				maxV = heap[right];
				maxPos = right;						
			}
			
			if(heap[node] < maxV){
				swap(heap[node], heap[maxPos]);
				node = maxPos;
			}else{
				break;
			}
		}
	}else{
		printf("0\n");
	}
}

void push(int x){
	heap.push_back(x);
	int node = heap.size() - 1, parent = node / 2;
	
	while(true){
		if(node == 0 && heap[node] < heap[parent]) break;
		
		if(node > 1 && heap[node] > heap[parent]){
			swap(heap[node], heap[parent]);
			node = parent;
			parent = node / 2;
		}else{
			break;
		}
	}
}

int main(){
	scanf("%d", &n);
	heap.push_back(0);
	
	for(int i = 0; i < n; i++){
		int x;
		scanf("%d", &x);
		
		if(x == 0){
			pop();
		}else{
			push(x);
		}
	} 
	
	return 0;
}
profile
ʜʏᴇᴘᴘʏ ᴅᴇᴠ

0개의 댓글