알고리즘

정렬(sort)

_jordy 2021. 8. 20. 21:49

https://www.toptal.com/developers/sorting-algorithms

정렬 알고리즘 퍼포먼스

 

선택 정렬(Selection Sort)

가장 작은 값을 찾아서 0번 인덱스에, 두번째로 작은 값을 찾아 1번 인덱스에 · · · =>일일히 하나씩 비교하여 가장 작은 값을 선택해서 앞으로 보냄

시간 복잡도 : O(N^2)

#include<iostream>
using namespace std;

int main(void) 
{
	int i, j, min, index, temp;
	int array[6] = { 4,2,7,9,3,1 };
	
	for (i = 0; i < 6; i++) {
		min = array[i];
		index = i;
		for (j = i; j < 6; j++) {
			if (min > array[j]) {
				min = array[j];
				index = j;
			}
		}
		temp = array[i];
		array[i] = array[index];
		array[index] = temp;
	}

	for (i = 0; i < 6; i++) {
		cout << array[i];
	}

	return 0;
}

버블 정렬(Bubble Sort)

숫자 오름차순 정렬, 옆에 있는 값과 비교하여 더 작은 값을 반복적으로 앞으로 보냄

vs 선택정렬 : 선택정렬의 경우 첫번째부터 마지막 -> 두번째부터 마지막 ... 순 

버블 정렬의 경우는 첫번째부터 마지막 -> 첫번째부터 마지막-1 ... 순 ∴ 한 번 반복 시 젤 큰 값이 맨 뒤에 위치

 

ex) 4 2 7 9 3 1

(1) 4 vs 2 더 작은 것 앞으로 => 2 4 7 9 3 1

(2) 4 vs 7 더 작은 것 앞으로 => 2 4 7 9 3 1

(3) 7 vs 9 더 작은 것 앞으로 => 2 4 7 9 3 1

(2) 9 vs 3 더 작은 것 앞으로 => 2 4 7 3 9 1

· · ·

1번 반복 결과 2 4 7 3 1 9

 

가장 비효율적인 알고리즘 , 시간 복잡도 : O(N^2)

#include<iostream>
using namespace std;

int main(void) 
{
	int i, j, temp;
	int array[6] = { 4,2,7,9,3,1 };
	
	for (i = 0; i < 6; i++) {
		for (j = 0; j < 5 - i; j++) {
			if (array[j] > array[j + 1]) {
				temp = array[j];
				array[j] = array[j + 1];
				array[j + 1] = temp;
			}
		}
	}

	for (i = 0; i < 6; i++) {
		cout << array[i];
	}

	return 0;
}

삽입 정렬(Insertion Sort)

수를 적절한 위치에 삽입함 (필요할 때만) => 데이터가 이미 거의 정렬된 상태에 한해서 가장 빠른 알고리즘

자신보다 작은 것을 만날 때 그 위치에 삽입함

시간 복잡도 : O(N^2)

 

ex) 4 2 7 1 9 3

4 vs 2 => 4를 한 칸 뒤로 이동시킨 후 빈칸에 2 삽입 -> 2 4 7 1 9 3

1 vs 7 -> 1 vs 4 -> 1 vs 2 => 7, 4, 2 순으로 모두 한 칸 뒤로 이동시킨 후 빈칸에 1 삽입 -> 1 2 4 7 9 3

· · ·

#include<iostream>
using namespace std;

int main(void) 
{
	int i, j, key;
	int array[6] = { 4,2,7,9,3,1 };
	
	//index 0 은 이미 정렬된 것으로 봄
	for (i = 1; i <= 5; i++) {
		j = i;

		key = array[i];

		for (j = i - 1; j >= 0 && array[j] > key; j--) {
			array[j + 1] = array[j]; //오른쪽으로 이동
		}

		array[j + 1] = key;
	}

	for (i = 0; i < 6; i++) {
		cout << array[i];
	}

	return 0;
}

#include<iostream>
using namespace std;

int main(void) 
{
	int i, j, temp;
	int array[6] = { 4,2,7,9,3,1 };
	
	for (i = 0; i < 5; i++) { //j=i, j+1 때문에 i<5
		j = i;

		while (j >= 0 && array[j] > array[j + 1]) {
			temp = array[j];
			array[j] = array[j + 1];
			array[j + 1] = temp;
			j--;
		}
	}

	for (i = 0; i < 6; i++) {
		cout << array[i];
	}

	return 0;
}


퀵 정렬(Quick Sort)

divide and conquer

시간 복잡도 : O(N*logN)

이미 정렬 되어있는 경우(최악의 경우) 시간 복잡도 : O(N^2)

★Partition★

: pivot(기준값)을 기준으로 pivot보다 작은 값은 왼쪽에 큰 값은 오른쪽에 배치

 


병합 정렬(Merge Sort)

divide and conquer

=> divide : 반으로 나눔, conquer : 왼쪽과 오른쪽을 각각 정렬, combine : 정렬된 두개를 하나로 합병

시간 복잡도 : O(N*logN) ->최악의 경우에도 보장

하나의 큰 문제를 두개의 작은 문제로 분할한 뒤 각자 계산하고 나중에 합침(일단 반으로 나누고 나중에 정렬)

=>합치는 순간에 정렬을 수행

 

 


힙 정렬(Heap Sort)

힙 트리 구조(heap tree structure) 이용

시간 복잡도 : O(N*logN)

 

더보기

이진 트리(binary tree) : 모든 노드의 자식 노드가 2개 이하인 노드

완전 이진 트리 : 데이터가 루트(root)노드로 부터 시작하여 자식 노드가 왼쪽자식노드, 오른쪽 자식 노드로 차근차근 들어가는 구조의 이진트리(이진 트리의 노드가 중간에 비어있지 않고 가득 찬 구조)

힙(heap) : 최솟값이나 최댓값을 빠르게 찾아내기 위해 완전 이진 트리를 기반으로 하는 트리

-> 최대 힙 : 부모노드가 자식노드보다 큰 힙

 

'알고리즘' 카테고리의 다른 글

기본STL정리  (0) 2021.08.12
스택, 큐, 덱  (0) 2021.03.12
그래프, 트리  (0) 2021.03.07
동적계획법(Dynamic Programming)  (0) 2021.02.17