record logo record

힙 정렬(Heap Sort) 이란?

힙 정렬(Heap Sort) 알고리즘의 특징

힙 정렬(Heap Sort)의 알고리즘 예시

힙 구조로 변경하는데 걸리는 시간 복잡도는 O(N * logN)이다.

// 전체 트리 구조를 최대 힙 구조로 바꾼다. 
for(int i = 1; i < num; i++){
	int c = i;
	do {
		// 특정 원소의 부모 
		int root = (c - 1) / 2;
		if(heap[root] < heap[c]){
			int tmp = heap[root];
			heap[root] = heap[c];
			heap[c] = tmp;
		}
		c = root;
		for(int i=0; i < num; i++){
			printf("%d ",heap[i]);
		}
		printf("\n");
	} while (c != 0);
	
}

힙 정렬 구현하기

C++ 예시1(최대 힙, 일반 구현법)

#include <stdio.h>

int num = 9;
int heap[9] = {7, 6, 5, 8, 3, 5, 9, 1, 6};

int main(void){
	// 전체 트리 구조를 최대 힙 구조로 바꾼다. 
	for(int i = 1; i < num; i++){
		int c = i;
		do {
			// 특정 원소의 부모 
			int root = (c - 1) / 2;
			if(heap[root] < heap[c]){
				int tmp = heap[root];
				heap[root] = heap[c];
				heap[c] = tmp;
			}
			c = root;
			for(int i=0; i < num; i++){
				printf("%d ",heap[i]);
			}
			printf("\n");
		} while (c != 0);
		
	}
	// 크기를 줄여가며 반복적으로 힙을 구성한다.
	for(int i = num - 1; i >= 0; i--){
		int tmp = heap[0];
		heap[0] = heap[i];
		heap[i] = tmp;
		int root = 0;
		int c = 1;
		do {
			c = 2 * root + 1;
			// 자식 중에 더 큰 값을 찾기
			if(heap[c] < heap[c+1] && c < i-1){
				c++;
			}
			// 루트보다 자식이 더 크면 교환 
			if(heap[root] < heap[c] && c < i){
				int tmp = heap[root];
				heap[root] = heap[c];
				heap[c] = tmp;
			}
			root = c;
		} while (c < i);
	} 
	printf("결과 \n");
	// 결과 출력 
	for(int i=0; i < num; i++){
		printf("%d ",heap[i]);
	}
	
	return 0;
}

C++ 구현예시2(최대 힙, 최소 힙, 빠른 구현법)

/*
 * Max Heap
 */
#include <bits/stdc++.h>
using namespace std;
int heap_size;
int heap[10001];

int max_push(int data) {
	int target = heap_size + 1;
	//루트노드가 data보다 작으면 자식노드로 복사
	while (target != 1 && heap[target/2] < data) {
		heap[target] = heap[target/2];
		target /= 2;
	}
	heap[target] = data;
	heap_size++;
}
void max_pop() {
	int parent = 1, child = 2;
	int last = heap[heap_size];
	while (child < heap_size) {
		//right 유무 && left가 right보다 작을때 
		if(child+1 < heap_size && heap[child] < heap[child+1]) {
			child++;//큰 값 선택(right)
		}
		if(last >= heap[child]) {//마지막 노드가 자식 보다 크거나 같으면 종료
			break;
		}
		//그렇지 않으면 자식 노드를 루트에 저장
		heap[parent] = heap[child];
		parent = child;
		child *= 2;
	}
	heap[parent] = last;
	heap_size--;
}
void solve() {
	//input
	int arr[10] = {4,3,2,6,3,8,9,1,7,5};
	for (int i = 0; i < 10; i++){
		max_push(arr[i]);
	}
	//Max Heap Result
	for (int i = 0; i < 10; i++){
		cout << heap[1] << " ";
		max_pop();
	}
}
int main(void){
	ios::sync_with_stdio(false);
    cin.tie(nullptr);
	solve();
	return 0;
}
/* 
 * Min Heap 
 */
#include <bits/stdc++.h>
using namespace std;
int heap_size;
int heap[10001];

int min_push(int data) {
	int target = heap_size + 1;
	//루트노드가 data보다 크면 자식노드로 복사
	while (target != 1 && heap[target/2] > data) {
		heap[target] = heap[target/2];
		target /= 2;
	}
	heap[target] = data;
	heap_size++;
}
void min_pop() {
	int parent = 1, child = 2;
	int last = heap[heap_size];
	while (child < heap_size) {
		//right 유무 && left가 right보다 클때
		if(child+1 < heap_size && heap[child] > heap[child+1]) {
			child++;//작은 값 선택(right)
		}
		if(last <= heap[child]) {//마지막 노드와 자식노드 중 작은 값
			break;
		}
		heap[parent] = heap[child];
		parent = child;
		child *= 2;
	}
	heap[parent] = last;
	heap_size--;
}
void solve() {
	//input
	int arr[10] = {4,3,2,6,3,8,9,1,7,5};
	for (int i = 0; i < 10; i++){
		min_push(arr[i]);
	}
	//Min Heap Result
	for (int i = 0; i < 10; i++){
		cout << heap[1] << " ";
		min_pop();
	}
}
int main(void){
	ios::sync_with_stdio(false);
    cin.tie(nullptr);
	solve();
	return 0;
}

Java 예시1(최대 힙, 최소 힙)

class Main {
	static int[] maxHeap = new int[10001];
	static int maxHeapSize;

	static int[] minHeap = new int[10001];
	static int minHeapSize;

	/*
	 * Max Heap
	 */
	public static void maxPush(int data) {
		int target = maxHeapSize + 1;
		while(target != 1 && maxHeap[target/2] < data){
			maxHeap[target] = maxHeap[target/2];
			target /= 2;
		}
		maxHeap[target] = data;
		maxHeapSize++;
	}
	public static void maxPop() {
		int parent = 1, child = 2;
		int last = maxHeap[maxHeapSize];
		while(child < maxHeapSize) {
			if(child+1 < maxHeapSize && maxHeap[child] < maxHeap[child+1]) {
				child++;
			}
			if(last >= maxHeap[child]) break;
			maxHeap[parent] = maxHeap[child];
			parent = child;
			child *= 2;
		}
		maxHeap[parent] = last;
		maxHeapSize--;
	}
	/*
	 * Min Heap
	 */
	public static void minPush(int data) {
		int target = minHeapSize + 1;
		while(target != 1 && minHeap[target/2] > data){
			minHeap[target] = minHeap[target/2];
			target /= 2;
		}
		minHeap[target] = data;
		minHeapSize++;
	}
	public static void minPop() {
		int parent = 1, child = 2;
		int last = minHeap[minHeapSize];
		while(child < minHeapSize) {
			if(child+1 < minHeapSize && minHeap[child] > minHeap[child+1]) {
				child++;
			}
			if(last <= minHeap[child]) break;
			minHeap[parent] = minHeap[child];
			parent = child;
			child *= 2;
		}
		minHeap[parent] = last;
		minHeapSize--;
	}
	public static void main(String[] args) throws Exception {
		//input
		int[] data = {2,3,7,4,5,1,9,4,8,6};
		for (int i = 0; i < 10; i++) {
			maxPush(data[i]);
			minPush(data[i]);
		}
		//result
		System.out.println("===Max Heap===");
		for (int i = 0; i < 10; i++) {
			System.out.print(maxHeap[1]+" ");
			maxPop();
		}
		System.out.println("\n===Min Heap===");
		for (int i = 0; i < 10; i++) {
			System.out.print(minHeap[1]+" ");
			minPop();
		}
	}
}

힙 정렬(Heap Sort)의 시간복잡도

힙 정렬의 시간복잡도는 O(N*logN) 이다.

정렬 알고리즘 시간복잡도 비교

관련된 Post

References