봄봄.devlog

힙 정렬(Heap Sort) 본문

Computer Science/알고리즘

힙 정렬(Heap Sort)

jihyun03 2020. 8. 21. 18:16

힙정렬(Heap Sort)

완전 이진 트리를 기본으로 하는 힙(Heap) 자료구조를 기반으로 한 정렬 방식

 

퀵정렬과 병합정렬의 성능이 좋기 때문에 힙 정렬의 사용빈도가 높지는 않다. 하지만 힙 자료구조가 많이 활용되고 있는 것은 사실!

 

* 힙정렬 활용

 

1. 가장 크거나 가장 작은 값을 구할 때

최소힙 또는 최대힙의 루트값이기 때문에 한번의 힙 구성을 통해 구하는 것이 가능하다.

 

2. 최대 K만큼 떨어진 요소들을 정렬할 때

삽입정렬보다 더욱 개선된 결과를 얻어낼 수 있다. 

시간복잡도

■ heapify 함수 수행 시간

heapify 함수는 힙 구조를 만들기 위해 이진 트리에서 자식 노드와 순서를 바꾸는 재귀호출을 한다.

힙 이진 트리의 높이는 logN이다.

따라서 heapify 함수의 재귀호출 횟수는 logN이다.

따라서 heapify 함수의 수행 시간은 O(logN)이다.

 

■ buildHeap 함수 수행 시간

buildHeap 함수에는 N에 비례하는 for 루프가 있다.

이 for 루프에서 heapify 함수를 호출한다.

따라서 buildHeap 함수의 수행 시간은 O(NlogN)이다.

 

■ heapSort 함수 수행 시간

buildHeap 함수를 1회 호출한다.

heapify 함수를 N회 호출한다.

따라서 heapSort 함수의 수행 시간은 O(logN)이다.

 

평균 최선 최악
O(nlogn) O(nlogn) O(nlogn)

 

힙 정렬 과정

1. 최대(최소 힙)을 구성

2. 루트 노드는 가장 큰 값(가장 작은 값)이다. 마지막 요소와 바꾼 후, 힙의 사이즈 하나를 줄인다.

3. 바꾼 루트 노드의 값을 가지고 다시 최대(최소)힙 구조를 만들기 위해 heapify 함수를 호출한다.

 

 

루트 노드 11을 마지막 노드인 4와 바꾸고, 힙 사이즈를 -1 한 다음, 다시 최대 힙을 구성한다.

 

import java.util.Arrays;

public class 최대힙 {
	static void swap(int[] a, int i, int j) {
		int temp = a[i];
		a[i] = a[j];
		a[j] = temp;
	}

	// 힙 정렬 만들기
	static void buildHeap(int[] a) {
		int end = a.length-1;
		for(int i= end/2; i>0; --i) // 마지막 노드의 부모노드부터 거꾸로 Heap 조정 규칙 시작!
			heapify(a, i, end);
	}
	static void heapify(int[] a, int k, int end) {
		int left = 2*k, right = 2*k+1;
		int larger;
		// 왼쪽, 오른쪽 자식 노드 둘 다 있는 경우
		if(right <= end) {
			larger = (a[left] > a[right]) ? left : right;
		} else if(left <= end) larger = left; // 왼쪽 노드만 있는 경우
		else return; // 둘 다 없는 경우

		if(a[larger] > a[k]) { // 부모노드 a[k]보다 자식노드의 값이 더 클 때 swap한다.
			swap(a, larger, k);
			heapify(a, larger, end); // swap을 하고 다시 자식노드와 그 아래 자식 노드들 힙 조정 규칙
		}
	}

	// 가장 큰 값인 루트노드부터 이진 트리에서 제거한다.
	static void heapSort(int[] a) {
		buildHeap(a); // 최대힙의 구조로 만들기
		System.out.printf("최대힙 구조 : %s \n", Arrays.toString(a));
		for(int end=a.length-1; end>=1; --end) {
			swap(a, 0, end); // 마지막 노드와 루트 노드와 교환
			heapify(a, 0, end-1); // 제거한 노드를 빼고 다시 힙을 조정, end-1 주의! 배열 마지막 값부터 정렬
		}
	}

	public static void main(String[] args) {
		int[] a = {0, 3, 8, 2, 10, 4, 6, 7, 1, 9, 5};
		heapSort(a);
		System.out.printf("힙소트 : %s \n",(Arrays.toString(a)));
	}
}

 

 

'Computer Science > 알고리즘' 카테고리의 다른 글

위상정렬(Topology Sort)  (0) 2020.10.22
Dynamic Programming(동적계획법)  (0) 2020.09.24
그리디 알고리즘  (0) 2020.08.14
Comments