데이터를 정해진 기준에 따라 배치해 의미 있는 구조로 재설정하는 것.
| 정렬 알고리즘 | 정의 |
|---|---|
| 버블 | 데이터의 인접 요소끼리 비교하고, swap 연산을 수행하며 정렬 |
| 선택 | 대상에서 가장 크거나 작은 데이터를 찾아가 선택을 반복하면서 정렬 |
| 삽입 | 대상을 선택해 정렬된 영역에서 선택 데이터의 적절한 위치를 찾아 삽입하면서 정렬 |
| 퀵 | pivot 값을 선정해 해당 값을 기준으로 정렬 |
| 병합 | 이미 정렬된 부분 집합들을 효율적으로 병합해 전체를 정렬 |
| 기수 | 데이터으 ㅣ자릿수를 바탕으로 비교해 데이터를 정렬 |
vector<int> v(n); // 정렬되지 않은 n개의 원소를 가진 벡터가 있다고 가정
두 인접한 데이터의 크기를 비교해 정렬하는 방법.
시간 복잡도 : O(n^2)
for(int i = 0; i < n - 1; ++i)
{
for(int j = 0; j < n - 1 - i; ++j)
{
if(v[j] > v[j + 1]) // 인접한 데이터의 크기를 비교
{
int temp = A[j];
A[j] = A[j + 1];
A[j + 1] = temp;
}
}
}
대상 데이터에서 최대나 최소 데이터를 나열된 순으로 찾아가며 선택하는 방법.
시간 복잡도 : O(n^2)
int idx,min;
for(int i = 0; i < n; ++i)
{
min = INT_MAX;
for(int j = i; j < n; ++j)
{
if(v[j] < min)
{
min = v[j];
idx = j;
}
}
int temp = v[i];
v[i] = min;
v[idx] = temp;
}
이미 정렬된 데이터 범위에 정렬되지 않은 데이터를 적절한 위치에 삽입해 정렬하는 방법.
시간 복잡도 : O(n^2)
int key, idx;
for(int i = 1; i < n; ++i)
{
key = v[i];
for(int j = i - 1; j >= 0; --j)
{
if(v[j] > key)
v[j+1] = v[j];
else
break;
}
v[j+1] = key;
}
기준 값을 선정해 해당 값보다 작은 데이터와 큰 데이터로 분류하는 것을 반복해 정렬하는 방법.
평균 시간 복잡도 : O(n×log n), 최악 시간 복잡도 : O(n^2)
void quickSort(int start, int end) {
if (start >= end)
return;
int pivot = start; // 기준 값
int i = start + 1 , j = end;
while (i <= j)
{
while (v[i] <= v[pivot]) // 키 값보다 큰 값 만날때까지 오른쪽으로 이동
i++;
while (v[j] >= v[pivot] && j > start) // 키 값보다 작은 값 만날 때까지 왼쪽으로 이동
j--;
if (i > j) //현재 엇갈린 상태면 pivot 값 교체
{
int temp = v[j];
v[j] = v[pivot];
v[pivot] = temp;
}
else
{
int temp = v[j];
v[j] = v[i];
v[i] = temp;
}
// 재귀 호출
quickSort(start, j - 1);
quickSort(j + 1, end);
}
}
quickSort(0,n - 1); // 퀵 정렬
분할 정복 방식을 이용해 데이터를 분할하고 분할한 집합을 정렬하며 합치는 방법.
시간 복잡도 : O(n×log n)
평균적으로 퀵 정렬보다 느리지만, 메모리를 많이 먹는다는 단점이 존재한다.
vector<int> v2;
// 병합하며 정렬
void merge(int left, int right)
{
int mid = (left + right) / 2;
int i = left;
int j = mid + 1;
int k = left;
while (i <= mid && j <= right)
{
if (v[i] <= v[j])
v2[k++] = v[i++];
else
v2[k++] = v[j++];
}
int tmp = i > mid ? j : i;
while(k<= right)
v2[k++] = v[tmp++];
for (int i = left; i <= right; i++)
v[i] = v2[i];
}
// 분할을 재귀적으로 호출
void partition(int left,int right)
{
int mid;
if (left < right)
{
mid = (left + right) / 2;
partition(left, mid);
partition(mid + 1, right);
merge(left, right);
}
}
partition(0,n-1); // 병합 정렬
값을 놓고 비교할 자릿수를 정한 다음 해당 자릿수만 비교하는 방법.
시간 복잡도 : O(k×n) , k = 데이터의 자릿수
int n;
cin >> n;
int cnt[10001] = {0};
int number = 0;
for(int i = 1; i <= n; ++i)
{
cin >> number;
cnt[number]++;
}
for(int i = 0; i <= 10000; ++i)
{
if(cnt[i] != 0)
{
for(int j = 0; j < cnt[i]; ++j)
cout << i << '\n';
}
}
