HolaJun

35 object(s)
 

Heap_sort

힙 정렬(Heap Sort)

힙(Heap) 이란?

최댓값 및 최솟값을 찾아내는 연산을 빠르게 하기 위해 고안된 완전이진트리(Complete Binary Tree)를 기본으로 한 자료구조.

힙 예시

힙에 대한 이미지 검색결과

힙 데이터 삽입(Heap Insert)

  1. 가장 끝 자리에 노드 삽입
  2. 그 노드와 부모 노드 서로 비교
  3. 규칙(최대힙 or 최소힙)에 맞으면 그대로 두고, 그렇지 않으면 부모와 교환
  4. 규칙에 맞을 때 까지 3번 과정 반복

힙 데이터 삭제(Heap Delete)

  1. 루트 노드 제거
  2. 루트 자리에 가장 마지막 노드 삽입
  3. 루트 자리에 올라간 노드와 자식 노드 비교
  4. 조건(최대힙 or 최소힙)에 만족하면 그대로 두고, 그렇지 않으면 자식과 교환
    • 최대힙
      1. 부모보다 더 큰 자식이 없으면 교환하지 않고 끝냄
      2. 부모보다 더 큰 자식이 하나만 있으면 그 자식과 교환
      3. 부모보다 더 큰 자식이 둘 있으면 자식들 중 큰 값과 교환
    • 최소힙
      1. 부모보다 더 작은 자식이 없으면 교환하지 않고 끝냄
      2. 부모보다 더 작은 자식이 하나만 있으면 그 자식하고 교환
      3. 부모보다 더 작은 자식이 둘 있으면 자식들 중 작은 값과 교환
  5. 조건을 만족할 때까지 4의 과정 반복

알고리즘

  1. 주어진 배열을 최대힙 or 최소힙으로 만든다.
  2. 최대 힙의 루트노드(최댓값)와 말단노드(가장 마지막 요소) 교환
  3. 새 루트노드에 대해 최대힙 구성
  4. 원소의 개수만큼 2~3단계 반복 수행

시간복잡도

힙 정렬의 시간복잡도는 nlogn

힙 구현 코드

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

# define MAX_SIZE 25
# define RAND_RANGE 100

////// 전역변수 선언 
clock_t second = 0;
int data[MAX_SIZE] = {};
int sortedOfMergeArray[MAX_SIZE] = {};
int length = sizeof(data)/sizeof(int); // 배열의 크기

////// 함수 선언
void Swap(int *arr, int a, int b);
void seed_init();
void random_number(int *array, int length);
void printArray(int *array);
void selection_sort(int *array, int length);
void bubble_sort(int *array, int length);
void quick_sort(int *array, int start, int end);
void merge_sort(int *data, int start, int end);
void merge(int *data, int start, int mid, int end);
void heap_sort(int *array, int size);
void heap_heapify(int *array, int size, int i);

int main() {
	seed_init();
		
	// 힙 정렬 
	random_number(data, length);
	printf("\n\nHeap Sort\n");
	printf("정렬 전: ");
	printArray(data);
	second = (int)clock();
	heap_sort(data, length);
	printf("\n정렬 후: ");	
	printArray(data);
	printf("\n데이터 %d개의 정렬 수행시간: %0.4f초\n", length, (float)(clock() - second) /CLOCKS_PER_SEC);
	
	return 0;
}

// 스왑 함수 
void Swap(int *arr, int a, int b) {
	int temp = arr[a];
	arr[a] = arr[b];
	arr[b] = temp;
}

// 난수에 매번 다른 시드를 주기 위한 함수 
void seed_init() {
	srand((unsigned int)time(NULL));
} 

// 난수 발생 함수 
void random_number(int *array, int length) {
	bool overlapCheck = false; // 원소값 중복체크 변수 
	 
	for(int i=0; i<length; i++) {
		while(true) {
			array[i] = (rand()%RAND_RANGE)+1;
			overlapCheck = false;
			
			for(int j=0; j<i; j++) {
				if(array[j] == array[i]) {
					overlapCheck = true;
					break;
				}
			}
			if(!overlapCheck) {
				break;
			}
		}	
	}	
}

// 배열 출력 
void printArray(int *array) {
	for(int i=0; i<length; i++) {
		printf("%d ", array[i]);
	}
	
}

// 힙 정렬 최대 최소힙 만들기 
void heap_heapify(int *array, int size, int i) {
	int left = 2*i+1; 
	int	right = 2*i+2; 
	int	largest = i;
	
	// array[left]>array[largest], array[right]>array[largest] => 최소힙
	//array[left]<array[largest], array[right]<array[largest] => 최대힙 
	
	// 해당 노드가 largest보다 크면 교환 
	if( left<size && array[left] < array[largest] ) {
		largest=left;
	}
	// 해당 노드가 largest보다 크면 교환 
	if( right<size && array[right] < array[largest] ) {
		largest=right;
	}
	if( largest == i ) { 
		return;
	}
	Swap(array, i, largest);
	
	heap_heapify(array, size, largest);
}

// 힙 정렬 
void heap_sort(int *array, int size) {
	for(int i=size/2-1; i>=0; i--) {
		heap_heapify(array, size, i);	
	}
	
	for(int i=size-1; i>=0; i--) {
		Swap(array, 0, i);
		heap_heapify(array, i, 0);
	}
}

결과

selection_sort