Heap Sort

Young·2024년 2월 24일
post-thumbnail
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.StringTokenizer;

public class Main {
    public static class IntHeapSort {
        ArrayList<Integer> heap;
        int numberOfExchanges;
        int exchangeNumberCheck;
        ArrayList<Integer> snapshot;
        public IntHeapSort(int size, int checkNumber) {
            heap = new ArrayList<Integer>(size + 1);
            heap.add(0); // dummy
            exchangeNumberCheck = checkNumber;
        }
        private void buildMinHeap(ArrayList<Integer> heap, int size) {
            //    build_min_heap(A[], n) {
            //        for i <- ⌊n / 2⌋ downto 1
            //        heapify(A, i, n)
            //    }

            for (int i = (size / 2); i >= 1; --i) {
                heapify(heap, i, size);
            }
        }
        private void heapify(ArrayList<Integer> heap, int i, int size) {
            //# A[k]를 루트로 하는 트리를 최소 힙 성질을 만족하도록 수정한다.
            //# A[k]의 두 자식을 루트로 하는 서브 트리는 최소 힙 성질을 만족하고 있다.
            //            # n은 배열 A의 전체 크기이며 최대 인덱스를 나타낸다.
            //    heapify(A[], k, n) {
            //        left <- 2k; right <- 2k + 1;
            //        if (right ≤ n) then {
            //            if (A[left] < A[right]) then smaller <- left;
            //                                else smaller <- right;
            //        }
            //    else if (left ≤ n) then smaller <- left;
            //    else return;
            //
            //    # 최소 힙 성질을 만족하지 못하는 경우 재귀적으로 수정한다.
            //        if (A[smaller] < A[k]) then {
            //            A[k] <-> A[smaller];
            //            heapify(A, smaller, n);
            //        }
            //    }

            int leftChild = 2 * i;
            int rightChild= 2 * i + 1;
            int smaller;
            if (rightChild <= size) {
                if (heap.get(leftChild) < heap.get(rightChild)) {
                    smaller = leftChild;
                } else {
                    smaller = rightChild;
                }
            } else if (leftChild <= size) {
                smaller = leftChild;
            } else return;

            if (heap.get(smaller) < heap.get(i)) {
                Integer temp = heap.get(i);
                heap.set(i, heap.get(smaller));
                heap.set(smaller, temp);

                numberOfExchanges++;
                if (numberOfExchanges >= exchangeNumberCheck) {
                    snapshot = new ArrayList<>(heap);
                    throw new RuntimeException("허용 교환 횟수 초과");
                }

                heapify(heap, smaller, size);
            }
        }
        public void heapSort() throws RuntimeException {
            //    heap_sort(A[1..n]) { # A[1..n]을 정렬한다.
            //        build_min_heap(A, n);
            //        for i <- n downto 2 {
            //            A[1] <-> A[i];  # 원소 교환
            //            heapify(A, 1, i - 1);
            //        }
            //    }

            int lastIdx = heap.size() - 1;
            buildMinHeap(heap, lastIdx);
            for (int i = lastIdx; i >= 2; --i) {
                Integer temp = heap.get(i);
                heap.set(i, heap.get(1));
                heap.set(1, temp);

                numberOfExchanges++;
                if (numberOfExchanges >= exchangeNumberCheck) {
                    snapshot = new ArrayList<>(heap);
                    throw new RuntimeException("허용 교환 횟수 초과");
                }

                heapify(heap, 1, i - 1);
            }
        }

        public int getNumberOfExchanges() {
            return numberOfExchanges;
        }

        public ArrayList<Integer> getSnapshot() {
            return snapshot;
        }
    }
    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        StringTokenizer st = new StringTokenizer(bf.readLine(), " ");
        int numberOfElements = Integer.parseInt(st.nextToken());
        int exchangeNumberCheck = Integer.parseInt(st.nextToken());

        IntHeapSort intHeapSort = new IntHeapSort(numberOfElements, exchangeNumberCheck);

        st = new StringTokenizer(bf.readLine()," ");
        for(int i = 0 ; i < numberOfElements ; i++){
            intHeapSort.heap.add(Integer.parseInt(st.nextToken()));
        }
        bf.close();;

        boolean overflow = false;

        try {
            intHeapSort.heapSort();
        } catch (RuntimeException e) {
            overflow = true;
            ArrayList<Integer> snapshot = intHeapSort.getSnapshot();
            for (int i = 1; i <= snapshot.size() - 1 ; ++i) {
                bw.write(String.valueOf(snapshot.get(i)));
                bw.write(" ");
            }
        }

        if (!overflow) {
            bw.write("-1");
        }

        bw.flush();
        bw.close();
    }
}

문제 바로가기:
http://boj.kr/a466262188ea48a78c7f1c6635942ee5
썸네일 출처:
https://yuminlee2.medium.com/heap-sort-algorithm-6e200dc51845

profile
생각을 영하게

0개의 댓글