λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
μ•Œκ³ λ¦¬μ¦˜/자료ꡬ쑰 이둠

νž™(Heap) - 자료ꡬ쑰

by sh119 2024. 6. 22.

πŸ‘©‍πŸ’» Heap μ΄λž€?

λΉ„μ„ ν˜• 자료ꡬ쑰둜 트리 기반의 μžλ£Œκ΅¬μ‘°μ΄λ‹€. μ΅œλŒ€ νž™(Max Heap), μ΅œμ†Œ νž™(Min Heap)이 μžˆλ‹€. 

μ΅œλŒ€ νž™μ—μ„œλŠ” λΆ€λͺ¨ λ…Έλ“œκ°€ μžμ‹ λ…Έλ“œλ³΄λ‹€ ν¬κ±°λ‚˜ κ°™κ³ , μ΅œμ†Œ νž™μ—μ„œλŠ” λΆ€λͺ¨ λ…Έλ“œκ°€ μžμ‹ λ…Έλ“œλ³΄λ‹€ μž‘κ±°λ‚˜ κ°™λ‹€.

Heap은 μ™„μ „ 이진 트리(Complete Binary Tree) 기반으둜 λ§Œλ“€μ–΄μ‘ŒμœΌλ©° 이진 νž™(Binary Heap)은 κ°€μž₯ 일반적인 ν˜•νƒœμ΄λ‹€.

μš°μ„ μˆœμœ„ 큐λ₯Ό μœ„ν•˜μ—¬ λ§Œλ“€μ–΄μ‘ŒμœΌλ―€λ‘œ μš°μ„ μˆœμœ„ 큐λ₯Ό κ΅¬ν˜„ν•  λ•Œ μ‚¬μš©λ˜λ©° μ΅œλŒ€κ°’μ΄λ‚˜ μ΅œμ†Œκ°’μ„ λΉ λ₯΄κ²Œ 찾을 수 μžˆλ‹€.

 

νž™μ€ μΌμ’…μ˜ 반 μ •λ ¬ μƒνƒœλ₯Ό μœ μ§€ν•œλ‹€.(큰 값이 μƒμœ„ λ ˆλ²¨μ— μžˆκ±°λ‚˜ μž‘μ€ 값이 ν•˜μœ„ λ ˆλ²¨μ— μžˆλ‹€. )

λ˜ν•œ νž™ νŠΈλ¦¬μ—μ„œλŠ” μ€‘λ³΅λœ 값을 ν—ˆμš©ν•œλ‹€. (이진 탐색 νŠΈλ¦¬μ—μ„œλŠ” μ€‘λ³΅λœ 값을 ν—ˆμš©ν•˜μ§€ μ•ŠλŠ”λ‹€.)

 

즉, νž™μ€ μ΅œλŒ€νž™ or μ΅œμ†Œνž™μ„ μ΄μš©ν•˜μ—¬ μ΅œλŒ€κ°’ or μ΅œμ†Œκ°’μ„ μ°ΎλŠ”λ° μœ λ¦¬ν•˜λ©° μ•„λž˜μ™€ 같은 νŠΉμ§•μ„ κ°–λŠ”λ‹€.

  • μ™„μ „ 이진 트리 ν˜•νƒœ
  • 쀑볡 κ°’ ν—ˆμš©
  • 반 μ •λ ¬ μƒνƒœ

* Tree에 λŒ€ν•œ 정리글 : https://sohyun119.tistory.com/32

 

✏️ μ‹œκ°„ λ³΅μž‘λ„

μ‚½μž… μ‚­μ œ : O(logn) (맀우 효율적인 νŽΈμ΄λ‹€)

μ΅œλŒ€κ°’ or μ΅œμ†Œκ°’μ„ μ°ΎλŠ” μ‹œκ°„ : O(1) (μ™œλƒν•˜λ©΄ 루트 λ…Έλ“œκ°€ μ΅œλŒ€ or μ΅œμ†Œλ₯Ό κ°€μ§€λ―€λ‘œ)

λ”°λΌμ„œ νž™μ€ μš°μ„ μˆœμœ„ 큐 이외에도 μ΅œλŒ€, μ΅œμ†Œκ°’μ„ μ°Ύκ±°λ‚˜ μ •λ ¬ν•  λ•Œμ— 많이 μ‚¬μš©λœλ‹€. 

 

 

✏️ νž™(heap)의 μ’…λ₯˜

 

1. μ΅œλŒ€νž™ (Max heap)

  • λΆ€λͺ¨ λ…Έλ“œμ˜ ν‚€ 값이 μžμ‹ λ…Έλ“œμ˜ ν‚€ 값보닀 ν¬κ±°λ‚˜ 같은 μ™„μ „ 이진 트리
  • key(λΆ€λͺ¨ λ…Έλ“œ) >= key(μžμ‹ λ…Έλ“œ)

2. μ΅œμ†Œνž™ (Min heap)

  • λΆ€λͺ¨ λ…Έλ“œμ˜ ν‚€ 값이 μžμ‹ λ…Έλ“œμ˜ ν‚€ 값보닀 μž‘κ±°λ‚˜ 같은 μ™„μ „ 이진 트리
  • key(λΆ€λͺ¨ λ…Έλ“œ) <= key(μžμ‹ λ…Έλ“œ)

 

✏️ νž™(heap)의 κ΅¬ν˜„

  • νž™μ„ μ €μž₯ν•˜λŠ” ν‘œμ€€μ μΈ μžλ£Œκ΅¬μ‘°λŠ” 배열이닀.
  • κ΅¬ν˜„μ„ μ‰½κ²Œ ν•˜κΈ° μœ„ν•΄ λ°°μ—΄μ˜ 첫 번째 index인 0은 μ‚¬μš©λ˜μ§€ μ•ŠλŠ”λ‹€.
  • νŠΉμ • μœ„μΉ˜μ˜ λ…Έλ“œ λ²ˆν˜ΈλŠ” μƒˆλ‘œμš΄ λ…Έλ“œκ°€ μΆ”κ°€λ˜μ–΄λ„ λ³€ν•˜μ§€ μ•ŠλŠ”λ‹€.
  • νž™μ—μ„œμ˜ λΆ€λͺ¨λ…Έλ“œμ™€ μžμ‹λ…Έλ“œ κ°„μ˜ 관계

     - μ™Όμͺ½ μžμ‹μ˜ index = (λΆ€λͺ¨μ˜ index) * 2

     - 였λ₯Έμͺ½ μžμ‹μ˜ index  = (λΆ€λͺ¨μ˜ index) * 2 + 1

     - λΆ€λͺ¨μ˜ index = (μžμ‹μ˜ index) / 2

 

 

 

 

✏️ κ΄€λ ¨ 문제 풀이

1. λ°±μ€€ 24174번 : νž™ μ •λ ¬2

이번 λ¬Έμ œλŠ” λ„ˆλ¬΄ 였래걸리고 μ–΄λ €μ› λ‹€γ…œγ…œ 보기에 μ£Όμ–΄μ§„ μ½”λ“œλž‘ λ‹€λ₯΄κ²Œ μ½”λ“œλ₯Ό μ²˜μŒλΆ€ν„°μ§°λ‹€κ°€ ν…ŒμŠ€νŠΈ μ½”λ“œλŠ” λ§žμœΌλ‚˜... 채점결과가 계속 ν‹€λ €μ„œ μ°¨κ·Όμ°¨κ·Ό λ¬Έμ œμ— μ£Όμ–΄μ§„ μ½”λ“œν‹€μ„ μ΄μš©ν•˜μ—¬ λ‹€μ‹œ ν’€μ–΄λ³΄μ•˜λ‹€... 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

class Solution{
    int count = 0;
    int k;
    int[] arr;

    public Solution(int[] arr, int k){
        this.arr = arr;
        this.k = k;
    }

    public String solution(){
        try{
            heapSort(arr);
        }catch (Exception e){
            return toString();
        }
        return "-1";
    }

    public void heapSort(int[] arr){
        int n = arr.length -1;
        buildMinHeap(arr, n);
        for(int i=n; i>=2; i--){
            swap(arr,1,i);
            heapify(arr, 1, i-1);
        }
    }
    public void buildMinHeap(int[] arr, int n){
        for(int i=n/2; i>=1; i--){
            heapify(arr, i, n);
        }
    }
    // arr[node]λ₯Ό 루트둜 ν•˜λŠ” 트리λ₯Ό μ΅œμ†Œ νž™ μ„±μ§ˆμ„ λ§Œμ‘±ν•˜λ„λ‘ μˆ˜μ •ν•œλ‹€.
    // arr[node]의 두 μžμ‹μ„ 루트둜 ν•˜λŠ” μ„œλΈŒ νŠΈλ¦¬λŠ” μ΅œμ†Œ νž™ μ„±μ§ˆμ„ λ§Œμ‘±ν•˜κ³  μžˆλ‹€.
    // n은 λ°°μ—΄ arr의 전체 크기이며 μ΅œλŒ€ 인덱슀λ₯Ό λ‚˜νƒ€λ‚Έλ‹€.
    public void heapify(int[] arr, int node, int n){
        int smaller = 0;
        int left = 2 * node;
        int right = 2 * node + 1;
        if(right <= n){
            if(arr[left] < arr[right]){
                smaller = left;
            }else{
                smaller = right;
            }
        } else if (left <= n) {
            smaller = left;
        } else{
            return;
        }
        // μ΅œμ†Œ νž™ μ„±μ§ˆμ„ λ§Œμ‘±ν•˜μ§€ λͺ»ν•˜λŠ” 경우 μž¬κ·€μ μœΌλ‘œ μˆ˜μ •
        if(arr[smaller] < arr[node]){
            swap(arr, smaller, node);
            // smallerκ°€ λ£¨νŠΈλ…Έλ“œκ°€ λ˜μ–΄ μž¬κ·€ν•¨μˆ˜ μ‹€ν–‰
            heapify(arr, smaller, n);
        }
    }
    public void swap(int[] arr, int i, int j){
        int temp = arr[j];
        arr[j] = arr[i];
        arr[i] = temp;
        if(++count == k){
            throw new RuntimeException(); //
        }
    }
    public String toString(){
        StringBuilder sb = new StringBuilder();
        for(int i=1; i<arr.length; i++){
            sb.append(arr[i]).append(" ");
        }
        return sb.toString();
    }

}
public class Main {
    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int n = Integer.parseInt(st.nextToken());
        int k = Integer.parseInt(st.nextToken());
        st = new StringTokenizer(br.readLine());
        int[] arr = new int[n + 1];
        arr[0] = 0;
        for (int i = 1; i <= n; i++) {
            arr[i] = Integer.parseInt(st.nextToken(" "));
        }

        System.out.println(new Solution(arr, k).solution());
    }
}

-> λ…ΈνŠΈμ— μ •λ¦¬ν•΄μ„œ λ‹€μ‹œ 곡뢀..