1. 버블 정렬 :
정렬 성능은 안좋지만 O(n^2) 빠르고 쉽게 구현 가능. 정렬이 중요한 문제가 아니라면 버블 정렬도 나쁘지 않음.
#define SWAP(a,b) {int t; t= b; b=a; a=t;}
int arr[5] = { 1,5,3,2,4 };
void bubble_sort(int arr_size) {
for (int fixed_p = arr_size -1; fixed_p > 0; fixed_p--) {
for (int bubble_p = 0; bubble_p < fixed_p; bubble_p++) {
if (arr[bubble_p] > arr[bubble_p+1]) { //5,3 일때 3,5로 바꿔줘야함
SWAP(arr[bubble_p], arr[bubble_p+1]);
}
}
}
}
#define SWAP(a,b) {int t; t=b; b=a; a=t; } 구문은 외워두고 활용하는게 좋음.
2. 병합 정렬 :
어떠한 경우에도 O(nlogn)의 성능을 가지지만 TEMP배열을 사용하기 때문에 메모리 낭비가 있음.
SWAP 과정이 없음.
int temp_arr[5]; //임시 배열 필요
void merge_sort(int start, int end) {
if (start >= end) return; //분할 종료 조건
int mid = (start + end) / 2; //arr을 반으로 나눌 기준값
merge_sort(start, mid); //반을 기준으로 왼쪽 분할 이 때 end는 중앙값이 됨.
merge_sort(mid + 1, end); //반을 기준으로 오른쪽 분할 이 때, start는 중앙값 +1이 됨
int left_point = start; //왼쪽 영역 시작 포인터
int right_point = mid + 1; //오른쪽 영역 시작 포인터
int temp_point = start; //임시 버퍼 시작 포인터
while (left_point <= mid && right_point <= end) {
if (arr[left_point] < arr[right_point]) temp_arr[temp_point++] = arr[left_point++]; //오른차순
else temp_arr[temp_point++] = arr[right_point];
}
while (left_point <= mid) temp_arr[temp_point++] = arr[left_point++]; //남아 있는 왼쪽 영역을 임시 버퍼로
while (right_point <= end) temp_arr[temp_point++] = arr[right_point++]; //남아 있는 오른쪽 영역을 임시 버퍼로
for (temp_point = start; temp_point <= end; temp_point++) arr[left_point] = temp_arr[left_point]; //임시버퍼의 값을 원배열에 복사
}
3. 힙정렬 :
최댓값 최솟값을 바로 찾을 때 사용
push 연산과 pop 연산 때 힙트리를 유지하기 위해 특별한 연산 필요
maximum heap -> 내림차순
minimum heap -> 오름차순
힙트리 시작은 0이 아니라 1부터 시작. 0은 버림. 맨 마지막 노드가 어딘지 알아야함.
int heap_arr[6]; //힙트리는 1부터 시작
int heap_last_p = 0; //힙트리의 마지막 노드를 가리킴
heap_push 는 자식이 부모를 타고 올라감
void heap_push(int data) {
if (heap_last_p == 5 + 1) {
//FULL일 때 더이상 못넣음.
return ;
}
heap_arr[++heap_last_p] = data; //heap트리는 전치연산을 함
//마지막에 push 후 이 값이 부모보다 큰지(maximum heap) or 작은지(minimum heap) 비교
int parent_p, children_p;
children_p = heap_last_p;
parent_p = children_p / 2; //부모는 자식 index의 1/2
//부모를 타고 올라가는 연산 필요.
while (parent_p > 0) {
//부모가 루트노드 일때 까지
if (heap_arr[children_p] < heap_arr[parent_p]) {
//minimum heap
SWAP(heap_arr[children_p], heap_arr[parent_p]);
//자식 index가 부모 index가 됨. (부모 타고 올라가기)
children_p = parent_p;
parent_p = children_p / 2;
}
else {
//이미 자식이 부모보다 크면 루트노드가 될 수 없음
break;
}
}
}
heap_pop은 부모가 자식을 타고 내려옴
void heap_pop(int* data) {
//EMPTY조건 체크
if (heap_last_p == 0) {
return;
}
//루트노드 heap_arr[1]를 pop
*data = heap_arr[1];
//맨 마지막 노드를 루트노드에 올림
heap_arr[1] = heap_arr[heap_last_p--];
//push와 반대로 부모에서 자식으로 내려가기 연산 필요
int parent_p, children_p, left_children_p, right_children_p;
//처음
parent_p = 1;
left_children_p = parent_p * 2;
right_children_p = left_children_p + 1;
//왼쪽 자식이 더이상 없을 때까지 내려가면서 비교. heap_last_p는 heap배열의 끝.
while (left_children_p <= heap_last_p) {
//내려왔더니 자식이 하나 뿐일 때
if (left_children_p == heap_last_p) {
//자식이 하나뿐이니 children_p에 그냥 넣는다.
children_p = left_children_p;
}
else {
//자식이 둘이면 둘 중 더 작은 것을 선택해야 한다.
if (heap_arr[left_children_p] < heap_arr[right_children_p]) {
children_p = left_children_p;
}
else {
children_p = right_children_p;
}
}
//자식을 선택 했다면 부모와 비교한다
if (heap_arr[children_p] < heap_arr[parent_p]) {
//부모가 더 크면 SWAP
SWAP(heap_arr[children_p], heap_arr[parent_p]);
//부모 다시 설정 후 자식 타고 내려가기 반복
parent_p = children_p;
left_children_p = parent_p * 2;
right_children_p = left_children_p + 1;
}
else break;
}
}
main에서 사용방법 : pop 할 때 나오는 값을 list에 따로 저장한다면 그게 바로 heap 정렬
//heap push
for (int i = 0; i < 5; i++) {
heap_push(arr[i]);
}
//heap pop
int data;
for (int i = 0; i < 5; i++) {
heap_pop(&data);
printf("%d\n", data);
}
4. 퀵정렬 :
void quick_sort(int s, int e) {
if (s >= e) return; //종료 조건
int left_p = s, target_p = s, pivot_p = e; //pivot은 end로 잡아줘야 구현 쉽다.
for (; left_p < e; left_p++) {
if (arr[left_p] < arr[pivot_p]) {
//pivot은 비교 대상 pivot보다 작으면 target_p과 교환이 이루어짐
//left_p 위치와 target_p 위치가 같으면 안됨
if (left_p != target_p) SWAP(arr[left_p], arr[target_p]);
target_p++;
}
}
if (target_p != pivot_p) SWAP(arr[target_p], arr[pivot_p]);
quick_sort(s, target_p - 1);
quick_sort(target_p + 1, e);
}
'삼성전자 알고리즘 > 자료구조 알고리즘' 카테고리의 다른 글
10. 트리 (0) | 2019.05.16 |
---|---|
9. 스택 (0) | 2019.05.16 |
7. 이진 탐색 [Binary Search] (0) | 2019.05.14 |
6. 힙(Heap) (0) | 2019.05.14 |
5. 우선순위 큐 (0) | 2019.05.14 |