힙 정렬 (Heap Sort)


힙 정렬 (Heap Sort)

  • 최대힙 트리나 최소힙 트리를 구성해 정렬하는 방법
  • 내림차순 정렬은 최대힙으로 구성
  • 오름차순 정렬은 최소힙으로 구성
  • 힙 관련 내용 참고 (https://banjjak1.tistory.com/45)

힙 정렬 방법

  • 내림차순일 경우 데이터를 최대힙으로 구성하고 오름차순일 경우 최소힙으로 구성
  • 최대힙의 경우 루트노드는 해당 트리에서 항상 최대값을 가지고 있으므로 힙 구성 후 삭제를 반복하면 다음 최대값이 루트노드가 되어 결국 내림차순 정렬이 됨

성능

  • 시간복잡도
    최악의 경우 : n log2(n)
    최선의 경우 : n log2(n)
     : 데이터 저장 및 삭제의 시간복잡도 log2(n)
     : 정렬할 데이터가 n개인 경우 n개의 데이터를 저장 및 삭제해야 하므로 n

  • 데이터 저장 및 삭제의 시간복잡도
     - 트리의 높이가 하나씩 증가할 때마다 데이터의 수는 증가 전 높이의 데이터 수보다 최대 2배 증가한다.
    그러나 데이터를 추가 및 삭제할 때는 부모노드와 같을 비교하기 때문에 데이터의 수는 2배 증가하지만 비교횟수는 1회 증가되는 것으로 이를 일반화하면 대략적으로 비교횟수 = log2(데이터 개수)이 된다.

구현

  • 기본 구현
    [HeapBasic.java]
    package Sort.Heap;
    
    import java.util.Collections;
    import java.util.PriorityQueue;
    
    public class HeapBasic {
        public static void sort(int[] arr, boolean isDescending) {
            PriorityQueue<Integer> pq = null;
            pq = init(isDescending);
            add(pq, arr);
    
            for(int i=0; i<arr.length; i++) {
                arr[i] = pq.remove();
            }
        }
    
        private static PriorityQueue init(boolean isDescending) {
            PriorityQueue pq = null;
            // 내림차순일 경우 최대힙으로 구성
            if (isDescending) {
                pq = new PriorityQueue<>(Collections.reverseOrder());
            }
            // 오름차순일 경우 최소힙으로 구성
            else {
                pq = new PriorityQueue<>();
            }
    
            return pq;
        }
    
        private static void add(PriorityQueue pq, int[] arr) {
            for(int i=0; i<arr.length; i++) {
                pq.add(arr[i]);
            }
        }
    
        private static int delete(PriorityQueue pq) {
            return (int)pq.remove();
        }
    }​


  • 테스트
    [HeapBasicMain.java]
    package Sort.Heap;
    
    public class HeapBasicMain {
        private static final int MAX_COUNT = 10;
    
        public static void main(String[] args) {
            int[] arr = new int[MAX_COUNT];
            for (int i = 0; i < MAX_COUNT; i++) {
                // 0 ~ MAX_COUNT 범위내의 난수를 생성
                arr[i] = (int) (Math.random() * MAX_COUNT);
            }
    
            System.out.println("정렬 전 데이터");
            for(int i : arr) {
                System.out.print(i + " ");
            }
            System.out.println();
    
            System.out.println("정렬 후 데이터 (오름차순)");
            int[] ascHeapSortTestArray = arr.clone();
            HeapBasic.sort(ascHeapSortTestArray, false);
            for(int i : ascHeapSortTestArray) {
                System.out.print(i + " ");
            }
            System.out.println();
    
            System.out.println("정렬 후 데이터 (내림차순)");
            int[] descHeapSortTestArray = arr.clone();
            HeapBasic.sort(descHeapSortTestArray, true);
            for(int i : descHeapSortTestArray) {
                System.out.print(i + " ");
            }
            System.out.println();
        }
    }​
  • 결과

 

+ Recent posts