728x90

선택 정렬(Selection Sort)

선택 정렬은 배열의 맨 앞부터 차례대로 가장 작은 값을 찾는 정렬 방법이다.

인덱스 0부터 시작해 배열의 가장 작은 값을 찾아 해당 위치와 스왑한다.

비교하는 횟수는 n-1, n-2, n-3, ... 1개씩 비교한다

따라서 시간 복잡도는 항상 O(N^2)이 된다.

 

버블 정렬(Bubble Sort)

버블 정렬은 매번 연속된 두 개의 인덱스를 비교하여, 마치 거품이 보글보글 올라가는 것 처럼 정렬하는 방식이다.

첫 번째 인덱스 부터 시작해서 바로 다음 인덱스를 비교해서, 다음 인덱스가 더 작다면 스왑한다.

다음 인덱스와 다다음 인덱스를 비교하는 식으로 계속 증가해서 끝까지 비교한다.

이렇게 한 싸이클을 돌고 나면 배열의 제일 오른쪽엔 제일 큰 숫자가 차례대로 정렬 될 것이다.

버블정렬 또한 시간 복잡도는 항상 O(N^2)이 된다.

 

삽입 정렬(Insertion Sort)

삽입 정렬은 특정 위치에서 그 이하의 배열들을 비교하며 자신이 들어갈 위치를 찾아 그 곳에 삽입하는 방식이다.

특정 위치는 두 번째 인덱스 부터 제일 마지막 인덱스까지 차례대로 증가한다. 

삽입 정렬의 시간 복잡도는 최악의 경우 O(N^2)이지만, 이미 정렬 되어있는 경우, 각 위치에서 한 번씩만 비교하기 때문에 O(N)이 된다.

 

합병 정렬(Merge Sort)

합병 정렬은 분할 정복 방식의 알고리즘이다.

 

분할 과정은 우선 배열을 반으로 나눈다. 쪼갠 배열의 크기가 0일때까지 반복한다.

 

합병 과정은 반으로 쪼갠 두 배열  A와 B를 합병한다.

A의 제일 왼쪽 인덱스와 B의 제일 왼쪽 인덱스를 차례대로 비교하며 더 작은 값을 임시 배열에 저장한다.

A와 B 둘 중 한 배열의 끝에 다다를때까지 해당 작업을 반복한 후, 아직 저장 못 한 남은 배열 값을 임시 배열에 저장한다.

그 후 원본 배열에 차례대로 정렬된 임시 배열 값을 적용한다.

 

합병 정렬의 시간 복잡도는 분할, 합병의 두 단계로 나눠서 생각한다.

분할 과정은 배열을 항상 반으로 나누므로 O(logN)이라 할 수있다.

합병 과정은 나눈 배열 A, B를 차례대로 모두 탐색하므로 O(N)이라 할 수 있다.

따라서 전체 시간 복잡도는 O(NlogN)이 된다.

 

퀵 정렬(Quick Sort)

퀵 정렬도 합병 정렬처럼 분할 정복 방식이다.

 

퀵 정렬은 특정 위치를 pivot으로 설정한다. 이 pivot을 기준으로 작은 값은 왼쪽, 큰 값은 오른쪽에 두는 방식으로 정렬한다.

pivot의 위치는 아무 위치나 설정해도 좋다. 보통 시작점, 끝점이나 중간 지점을 설정하는데 시작점으로 설정했다.

그 후 pivot 보다 큰 값을 찾을 left, 작은 값을 찾을 right 변수를 지정한다.

left의 위치는 pivot + 1로 즉 start+1이고, right의 위치는 배열의 끝 지점 즉 end 이다.

left는 1씩 증가하며 pivot보다 큰 값을 찾고, right는 1씩 감소하며 pivot보다 작은 값을 찾는다.

찾고 난 뒤에는 left와 right를 스왑한다. 이때 만약 right가 left보다 왼쪽에 위치하게 된다면, 즉 엇갈린다면 

pivot과 right를 스왑한 후 pivot을 중심으로 왼쪽, 오른쪽으로 분할한다.

 

퀵 정렬의 시간 복잡도는 O(NlogN)이지만, 미리 정렬되어 있는 최악의 경우 분할이 N번만큼 일어나기 때문에 O(N^2)이 된다.


 

코드 원본 : https://github.com/chosh95/STUDY/blob/master/Algorithm/%EC%A0%95%EB%A0%AC.cpp

 

chosh95/STUDY

프로그래밍 문제 및 알고리즘 정리. Contribute to chosh95/STUDY development by creating an account on GitHub.

github.com

 

C++ 코드

#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <vector>
using namespace std;

vector<int> selection_sort(const vector<int> input) {
	vector<int> v = input;
	for (int i = 0; i < v.size()-1; i++) {
		int tmp = i;
		for (int j = i + 1; j < v.size(); j++) {
			if (v[tmp] >= v[j]) tmp = j;
		}
		swap(v[i], v[tmp]);
	}
	return v;
}

vector<int> bubble_sort(const vector<int> input) {
	vector<int> v = input;
	for (int i = 0; i < v.size(); i++) {
		for (int j = 0; j < v.size()-i-1; j++) {
			if (v[j] > v[j+1]) swap(v[j], v[j+1]);
		}
	}
	return v;
}

vector<int> insertion_sort(const vector<int> input) {
	vector<int> v = input;
	for (int i = 1; i < v.size(); i++) {
		int key = v[i], j = i - 1;
		while (j >= 0 && key < v[j]) {
			swap(v[j], v[j+1]);
			j--;
		}
		v[j + 1] = key;
	}
	return v;
}

vector<int> merge(const vector<int> input, int start, int end, int med) {
	vector<int> v = input;
	vector<int> tmp;
	int i = start, j = med + 1;

	while (i <= med && j <= end) {
		if (v[i] < v[j]) tmp.push_back(v[i++]);
		else if (v[i] > v[j]) tmp.push_back(v[j++]);
	}

	while (i <= med) tmp.push_back(v[i++]);
	while (j <= end) tmp.push_back(v[j++]);

	for (int a = 0, b = start; b <= end; b++) {
		v[b] = tmp[a++];
	}
	return v;
}

vector<int> merge_sort(const vector<int> input, int start, int end) {
	vector<int> v = input;
	if (start < end) {
		int med = (start + end) / 2;
		v = merge_sort(v, start, med);
		v = merge_sort(v, med + 1, end);
		v = merge(v, start, end, med);
	}
	return v;
}

vector<int> quick_sort(const vector<int> input, int start, int end) {
	vector<int> v = input;
	if (start >= end) return v;
	int pivot = start, left = start + 1, right = end;
	while (left <= right) {
		while (left <= end && v[left] <= v[pivot]) left++;
		while (right > start && v[right] >= v[pivot]) right--;
		if (left > right) swap(v[pivot], v[right]);
		else swap(v[left], v[right]);
	}
	v = quick_sort(v, start, right - 1);
	v = quick_sort(v, right + 1, end);
	return v;
}
int main()
{
	vector<int> input;
	srand((unsigned int)time(NULL));
	for (int i = 0; i < 100; i++) {
		input.push_back(rand() % 10000 + 1);
	}

	cout << "selection sort\n";
	vector<int> res;
	res = selection_sort(input);
	for (int i = 0; i < res.size(); i++)
		cout << res[i] << " ";
	cout << endl << endl;

	cout << "bubble sort\n";
	res = bubble_sort(input);
	for (int i = 0; i < res.size(); i++)
		cout << res[i] << " ";
	cout << endl << endl;

	cout << "insertion sort\n";
	res = insertion_sort(input);
	for (int i = 0; i < res.size(); i++)
		cout << res[i] << " ";
	cout << endl << endl;

	cout << "merge sort\n";
	res = merge_sort(input,0,input.size()-1);
	for (int i = 0; i < res.size(); i++)
		cout << res[i] << " ";
	cout << endl << endl;

	cout << "quick sort\n";
	res = quick_sort(input, 0, input.size() - 1);
	for (int i = 0; i < res.size(); i++)
		cout << res[i] << " ";
	cout << endl << endl;
}
728x90

'알고리즘 > 기본 알고리즘' 카테고리의 다른 글

트리에서의 dp (백준 : 사회망 서비스(SNS) (2533번))  (0) 2020.10.22
disjoint-set (Union-Find)  (0) 2020.02.15
세그먼트 트리  (0) 2020.02.15
힙(Heap)  (0) 2020.02.12
KMP 알고리즘  (0) 2020.02.04

+ Recent posts