삽입정렬
시간복잡도 : O(n^2) , 최선의 경우 O(N)의 시간복잡도를 가진다.
선택정렬에 비해 난이도가 조금 높은 편이지만, 일반적으로 더 효율적으로 동작한다.
선택정렬과 버블정렬보다 조금 더 빠르고, 효율적이다.
처리하지 않은 데이터를 하나씩 골라 적절한 위치에 삽입한다.
#include <bits/stdc++.h>
using namespace std;
int n = 10;
int target[10] = {7, 5, 9, 0, 3, 1, 6, 2, 4, 8};
int main(void)
{
for (int i=1; i<n; i++)
{
for (int j=i; j>0; j--)
{
if (target[j] > target[j-1])
{
swap(target[j], target[j-1]);
}
else
{
break;
}
}
}
for (int i=0; i<n; i++)
{
cout << target[i] << ' ';
}
return 0;
}
선택정렬
N번만큼 가장 작은 수를 찾아서 맨 앞으로 보낸다.
시간복잡도 : O(n^2) = (N^2 + N - 2 / 2)
N + (N -1) + (N -2) + ... + 2
#include <bits/stdc++.h>
using namespace std;
int n = 10;
int target[10] = {7, 5, 9, 0, 3, 1, 6, 2, 4, 8};
int main(void)
{
for (int i=0; i<n; i++)
{
int min_index = i;
for (int j=i; j<n; j++)
{
if (target[min_index] > target[j])
{
min_index = j;
}
}
swap(target[i],target[min_index]);
}
for (int i=0; i<n; i++)
{
cout << target[i] << ' ';
}
return 0;
}
버블정렬
시간복잡도 : O(N^2)
선택정렬과 시간복잡도는 같지만 가장 느린 정렬알고리즘이다.
이유는 계속 왼쪽 숫자와 비교하며 교체하는 작업이 있기 때문이다.
선택정렬은 가장 작은 숫자를 골라서 마지막에 한번만 교체해준다.
#include <stdio.h>
int main(void)
{
int i, j, temp;
int target[10] = {7, 5, 9, 0, 3, 1, 6, 2, 4, 8};
for(i=0; i<10;i++)
{
for(j=0; j<9-i; j++)
{
if(target[j] > target[j+1])
{
temp = target[j];
target[j] = target[j+1];
target[j+1] = temp;
}
}
}
for(i=0; i<10; i++)
{
printf("%d ", target[i]);
}
return 0;
}
퀵정렬
시간복잡도 : 평균 - O(NlogN) , 최악의 경우 O(N^2) --> 이미 정렬이 수행이 되어 있는 경우. (1 2 3 4 5 6 7 8 9 10)
결과적으로 이미 정렬이 되어 있는 경우에는 삽입정렬 알고리즘이 매우 빠르게 풀어 낼 수 있다.
기준 데이터를 설정하고 기준보다 큰 데이터와 작은 데이터의 위치를 바꾸는 방법
가장 많이 사용되는 정렬 알고리즘이고, 프로그래밍 언어의 정렬 라이브러리의 근간이 되는 정렬 방법
이진탐색과 비슷한 방법이다.
#include <bits/stdc++.h>
using namespace std;
int n = 10;
int target[10] = {7, 5, 9, 0, 3, 1, 6, 2, 4, 8};
void quickSort(int *target, int start, int end)
{
if (start >= end) return;
int pivot = start;
int left = start + 1;
int right = end;
while (left <= right) // 엇갈릴 때 까지 반복
{
// 키 값 보다 큰 값을 만날때까지
while (left <= end && target[left] <= target[pivot]) left++;
// 키 값보다 작은 값을 만날때까지
while (right > start && target[right] >= target[pivot]) right--;
// 엇갈린 상태라면 pivot 값과 교체
if (left < right) swap(target[pivot], target[right]);
// 엇갈리지 않았다면 큰 값과 작은 값을 교체
else swap(target[left], target[right]);
}
// 데이터가 엇갈려서 while문을 빠져나온다면 pivot 값을 기준으로 왼쪽과 오른쪽에 대해서 퀵정렬을 수행한다.
quickSort(target, start, right - 1);
quickSort(target, right + 1, end);
}
int main(void)
{
quickSort(target,0,n-1);
for (int i=0; i<n; i++)
{
cout << target[i] << ' ';
}
return 0;
}
pivot은 기준 값이다. pivot은 첫 번째 원소이다.
퀵정렬은 재귀적으로 수행이 된다.
퀵정렬의 경우 위의코드는 오름차순 코드인데, 내림차순으로 바꾸려면
첫 while문 뒤의 2개의 while문에 있는 조건식의 부등호 방향만 바꿔주면 내림차순 코드가 된다.
결론 - 일반적으로는
버블정렬 < 선택정렬 < 삽입정렬 < 퀵정렬 순으로 선호된다.
하지만 결과적으로는 데이터의 특성에 따라서 적절한 정렬 알고리즘을 사용하는 것이 중요하다.
예를들어서 이미 정렬 된 데이터의 경우 퀵정렬보다 삽입정렬이 더 빠르게 풀어낼 수 있기 때문이다.
'Tech Blog > Online Coding Test' 카테고리의 다른 글
이진탐색 알고리즘(binary search) (0) | 2023.02.01 |
---|---|
파이썬 백준 for 문제 정복하기 (문제 11개) (0) | 2021.05.16 |
백준 파이썬 while 문제 풀기 (0) | 2021.05.07 |
파이썬 백준 if 문제 정복하기. (0) | 2021.05.04 |
파이썬 백준 1단계 [입출력과 사칙연산] 11문제 전부 정리! (0) | 2021.05.04 |