본문 바로가기
정렬

힙 정렬(Heap Sort)

by seogenius 2021. 4. 2.

힙 정렬(Heap Sort)

힙 자료구조를 이용하여 정렬.

힙은 완전 이진 트리에 있는 노드 중 키 값이 가장 큰 노드나 가장 작은 노드를 찾기 위해 만들어진 자료구조이다.

키 값이 가장 큰 노드를 찾기 위한 최대 힙(부모 키 >= 자식 키)을 이용해서 내림차순으로 정렬된 원소를 얻을 수 있고, 키 값이 가장 작은 노드를 찾기 위한 최소 힙(부모 키 <= 자식 키)을 이용해서 오름차순으로 정렬된 원소를 얻을 수 있다.

삭제 연산을 하면 루트 노드의 원소를 삭제하여 반환하는 힙의 특성을 이용해서 원소를 얻고 최대/최소 힙이 되도록 재구성하는 작업을 원소의 수만큼 반복하여 정렬한다.

n개의 노드에 대하여 삭제 연산을 하고 힙을 재구성 하는 시간 복잡도는 O(nlog2n)이다.

최대 힙 예시)

{57, 16, 41, 2, 50, 6, 32, 27}

1. 노드가 8개인 완전 이진 트리를 만든 후 최대 힙으로 구성한다.

           57

           /\

      50    41

      /\      /\

   32 27 16 6

   /

 1

2. 힙의 삭제 연산으로 루트 노드를 배열의 마지막 자리에 저장하고 남은 원소들을 최대 힙으로 재구성한다.

{57}

          50

           /\

      32    41

       /\      /\

    1   27 16  6

3. 힙의 삭제 연산으로 루트 노드를 배열의 남은 마지막 자리에 저장하고 남은 원소들을 최대 힙으로 재구성한다.

{50, 57}

          41

           /\

      32    16

       /\     /

     1  27 6

4. 힙의 삭제 연산으로 루트 노드를 배열의 남은 마지막 자리에 저장하고 남은 원소들을 최대 힙으로 재구성한다.

{41, 50, 57}

          32

           /\

       27  16

       /\

     1   6

5. 힙의 삭제 연산으로 루트 노드를 배열의 남은 마지막 자리에 저장하고 남은 원소들을 최대 힙으로 재구성한다.

{32, 41, 50, 57}

          27

           /\

        6   16

       /

     1

6. 힙의 삭제 연산으로 루트 노드를 배열의 남은 마지막 자리에 저장하고 남은 원소들을 최대 힙으로 재구성한다.

{27, 32, 41, 50, 57}

        16

        /\

      6   1

7. 힙의 삭제 연산으로 루트 노드를 배열의 남은 마지막 자리에 저장하고 남은 원소들을 최대 힙으로 재구성한다.

{16, 27, 32, 41, 50, 57}

      6

     /

   1

8. 힙의 삭제 연산으로 루트 노드를 배열의 남은 마지막 자리에 저장하고 남은 원소들을 최대 힙으로 재구성한다.

{6, 16, 27, 32, 41, 50, 57}

1

9. 힙의 삭제 연산으로 루트 노드를 배열의 남은 마지막 자리에 저장하고 힙이 공백이 되었으므로 종료한다.

{1, 6, 16, 27, 32, 41, 50, 57}

프로그램 작성)

package test;

class Sort {
	public void heapSort(int[] a) {
		makeHeap(a, a.length); 
		
		for(int i = a.length-1; i>0; i--) {
			swap(a, 0, i);
			
			// 교환 후 최대힙 재구성
			makeHeap(a, i); 
		}
	}
	
	public void makeHeap(int[] a, int num) {
		for(int i=1; i<num; i++) { 
			int child = i; 
			
			while(child > 0) { 
				int parent = (child-1)/2; 
				
				if(a[child] > a[parent]) { 
					swap(a, parent, child);
				} 
				
				child = parent; 
			} 
		}
	}
	
	public void swap(int[] a, int i, int j) {
		int temp = a[i];
		a[i] = a[j];
		a[j] = temp;
	}

}

public class Test {
	public static void main(String[] args) {
		int a[] = {57, 16, 41, 2, 50, 6, 32, 27};

		System.out.println("정렬 전 원소 : ");
		for(int i=0; i<a.length; i++) {
			System.out.printf(" %d", a[i]);
		}
		System.out.println();

		Sort s = new Sort();
		s.heapSort(a);

		System.out.println("정렬 후 원소 : ");
		for(int i=0; i<a.length; i++) {
			System.out.printf(" %d", a[i]);
		}
	}
}

실행 결과)

'정렬' 카테고리의 다른 글

트리 정렬(Tree Sort)  (0) 2021.04.02
기수 정렬(Radix Sort)  (0) 2021.04.02
병합 정렬(Merge Sort)  (0) 2021.04.02
셸 정렬(Shell Sort)  (0) 2021.04.02
삽입 정렬(Insert Sort)  (0) 2021.04.02