n개의 숫자가 입력으로 주어졌을 때, 이를 기준에 맞게 정렬하여 출력하는 알고리즘
정렬 알고리즘에는 다양한 종류가 있고, 이에 따라 수행 시간도 다양하다.
순차적으로 기준에 따라 현재 위치에 들어갈 값을 찾아 정렬
오름차순이면 Min-Selection Sort(최소 선택 정렬)
내림차순이면 Max-Selection Sort(최대 선택 정렬)
👍 장점
👎 단점
O(n^2)
(n-1, n-2, ..., 1개씩 비교 반복. 전체 비교를 진행하므로)O(n)
(하나의 배열에서만 진행하므로)#include
using namespace std;
void selectionSort(int arr[], int size) {
for(int i = 0 ; i < size - 1 ; i++) {
for (int j = i + 1 ; j < size ; j++) {
if(arr[i] > arr[j]) {
swap(arr[i], arr[j]);
}
}
}
}
int main() {
int arr[] = {9,8,7,4,2,6,1,3, 5};
int size = sizeof(arr) / sizeof(arr[0]);
selectionSort(arr, size);
for(int i = 0 ; i < size ; i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
출처: https://unikys.tistory.com/357 [All-round programmer]
연속된 두 개의 인덱스를 비교하여, 정한 기준의 값을 뒤로 넘겨 정렬한다.
오름차순이면 큰 값이 뒤로 이동
전체 배열의 크기 - 현재까지 순환한 바퀴 수
만큼 반복한다👍 장점
👎 단점
O(n^2)
(n-1, n-2, ..., 1개씩 비교 반복. 전체 비교를 진행하므로)O(n)
(하나의 배열에서만 진행하므로)#include
using namespace std;
void bubbleSort(int arr[], int size) {
bool isSwap;
do {
isSwap = false;
for (int i = 1 ; i < size ; i++) {
if (arr[i - 1] > arr[i]) {
swap(arr[i - 1] , arr[i]);
isSwap = true;
}
}
} while(isSwap);
}
int main() {
int arr[] = {9,8,7,4,2,6,1,3, 5};
int size = sizeof(arr) / sizeof(arr[0]);
bubbleSort(arr, size);
for(int i = 0 ; i < size ; i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
출처: https://unikys.tistory.com/357 [All-round programmer]
버블정렬의 비효율 성을 개선하기 위해 등장
현재 위치에서 그 이하의 배열들을 비교해 자신이 들어갈 위치를 찾아 그 위치에 삽입하여 정렬
👍 장점
👎 단점
O(n^2)
(n-1, n-2, ..., 1개씩 비교 반복. 전체 비교를 진행하므로)O(n)
(1번씩만 비교함)O(n)
(하나의 배열에서만 진행하므로)#include
using namespace std;
void insertionSort(int arr[], int size) {
for(int i = 0 ; i < size - 1 ; i++) {
for (int j = i + 1 ; j >= 0 ; j--) {
if(arr[j - 1] > arr[j]) {
swap(arr[j - 1], arr[j]);
} else {
continue;
}
}
}
}
int main() {
int arr[] = {9,8,7,4,2,6,1,3, 5};
int size = sizeof(arr) / sizeof(arr[0]);
insertionSort(arr, size);
for(int i = 0 ; i < size ; i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
출처: https://unikys.tistory.com/357 [All-round programmer]
Divede and conquer(분할 정복) 방식으로 설계된 알고리즘.
Divede and conquer(분할 정복)
큰 문제를 반으로 쪼개 해결해 나가는 방식.
배열을 왼쪽 절반, 오른쪽 절반으로 분할해 최소 단위로 쪼갠 후 합병하며 정렬한다.
👍 장점
👎 단점
합병
두 배열 A,B를 정렬하기 때문에 A배열 크기 = N1, B배열 크기 = N2 라 하면 O(N1+N2)
이때 N = N1+ N2 이므로 O(N)
이라고 할 수 있다.
분할
크기가 N인 배열을 분할하면 (N/2, N/2) -> (N/4, N/4, N/4, N/4) -> ... 이렇게 매번 반씩 감소한다.
lgN만큼 반복해야 크기가 1인 배열로 분할 할 수 있으므로 O(lgN)
이라고 할 수 있다.
시간 복잡도 : O(NlgN)
(각 분할별로 합병을 진행하므로)
공간 복잡도 : O(2N)
(정렬을 위한 배열을 하나 더 생성하므로)
#include <iostream>
using namespace std;
void mergeSort(int arr[], int size) {
if (size > 2) {
mergeSort(arr, size / 2);
mergeSort(arr + size / 2, size - size / 2);
int leftCursor = 0;
int rightCursor = size / 2;
int buff[50];
int buffCursor = 0;
while (leftCursor < size / 2 && rightCursor < size) {
if (arr[leftCursor] < arr[rightCursor]) {
buff[buffCursor++] = arr[leftCursor++];
} else {
buff[buffCursor++] = arr[rightCursor++];
}
}
for (int i = leftCursor ; i < size / 2 ; i++) {
buff[buffCursor++] = arr[i];
}
for (int j = rightCursor ; j < size ; j++) {
buff[buffCursor++] = arr[j];
}
memcpy(arr, buff, size * sizeof(int));
} else {
if (arr[0] > arr[1]) {
swap(arr[0], arr[1]);
}
}
}
int main() {
int arr[] = {9,8,7,4,2,6,1,3, 5};
int size = sizeof(arr) / sizeof(arr[0]);
mergeSort(arr, size);
for(int i = 0 ; i < size ; i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
출처: https://unikys.tistory.com/357 [All-round programmer]
Divede and conquer(분할 정복) 방식으로 설계된 알고리즘.
pivot point
라는 기준값을 설정해, 이 값을 기준으로 작은 값은 왼쪽, 큰 값은 오른쪽으로 옮기는 방식
이를 반복하여 분할된 배열의 크기가 1이 되면 모두 정렬된다.
최악의 경우에는 합병 정렬보다 느리지만 일반적으로는 퀵 정렬이 합병 정렬보다 20% 이상 빠르다.
pivot point
값을 설정한다. (보통 맨 앞이나 맨 뒤, 중간 인덱스 값이나 랜덤값으로 설정)pivot point
를 기준으로 작은 요소들은 왼쪽, 큰 요소들은 오른쪽으로 옮겨진다.pivot point
을 제외한 왼쪽 리스트와 오른쪽 리스트를 다시 정렬한다.👍 장점
👎 단점
O(NlgN)
(분할과 동시에 정렬을 진행, 각 정렬은 배열의 크기 N만큼 비교하며, 이를 총 분할 깊이인 lgN만큼 진행하므로 총 비교횟수는 NlgN)O(N^2)
(분할이 N만큼 일어나므로)O(log n)
(재귀적 호출로 발생)O(n)
#include <iostream>
using namespace std;
void quickSort(int arr[], int size) {
int pivot = arr[0];
int cursor = 0;
for (int i = 1; i < size ; i++) {
if (pivot > arr[i]) {
cursor++;
swap(arr[cursor], arr[i]);
}
}
swap(arr[0], arr[cursor]);
if (cursor > 0) {
quickSort(arr, cursor);
}
if (cursor + 1 < size - 1) {
quickSort(arr + cursor + 1, size - cursor - 1);
}
}
int main() {
int arr[] = {9,8,7,4,2,6,1,3,5};
int size = sizeof(arr) / sizeof(arr[0]);
quickSort(arr, size);
for(int i = 0 ; i < size ; i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
출처: https://unikys.tistory.com/357 [All-round programmer]