자료 정렬 알고리즘
- 자료정렬 (자료 처리의 기본)
- 자료를 원하는 기준에 맞게 순서를 재배치
- 자료저리의 효율성을 향상시키기 위한 작업
- 많은 양 중 원하는 정보를 찾고자 할 때 훨씬 빠르게 할 수 있음.
- 자료의 생성은 자료 내용을 컴퓨터에 저장한 후 효율적으로 사용하기 위함임
- 양이 많을 경우 정렬은 검색을 위한 우선단계가 됨.
- 정렬 → 검색 → 원하는 작업 실행 (이게 가장 효율적임)
- 기준값 = 키(key)값
- key 선택 -> 정렬 순서 방식 지정 (ex, 오름차순 / 내림차순)
- 정렬기준 정하기 → 자료 비교하기 → 자료 이동하기
- 선택정렬
- 오름차순의 선택 정렬은 배열된 자료의 값을 모두 비교
- 자료의 양이 적을 때 알고리즘 효율성이 좋으나 특정 값의 반복된 위치 교환이 있을 수 있음.
- 작은값 찾는 과정, 위치 교환하는 과정이 필요하므로 시간효율성이 낮음.
| 실행 과정 | 예시 | 8 4 7 3 5 |
| 가장 작은 값 선택 | 1) 가장 작은 값 3, 첫번째 자리 수 8 교환 | 3 4 7 8 5 |
| 첫 번째 자리 값과 위치 교환 | 2) 두번째 작은 값 4, 두번째 자리 수 4 => 자리 이동 x | 3 4 7 8 5 |
| 가장 작은 값부터 정렬 | 3) 세번째 작은 값 5, 세번째 자리수 7 교환 | 3 4 5 8 7 |
| 모두 정렬 될 때까지 계속 반복 | 4) 네번째 작은 값 7, 다섯번째 자리수 8 교환 | 3 4 5 7 8 |
| 전체 자료 정렬 n-1번 반복 (자료 개수 n개) | 전체 자료 개수 5개, 정렬 횟수 4회 |
// python 코드
def selection_sort(a):
for i in range(len(a)):
for j in range(i + 1, len(a)):
if a[i] > a[j]:
a[i], a[j] = a[j], a[i]
return a
// c++ 코드
vector<int> selection_sort(vector<int> a) {
for (int i = 0; i < a.size(); i++) {
for (int j = i + 1; j < a.size(); j++) {
if (a[i] > a[j]) swap(a[i], a[j]);
}
}
return a;
}
- 버블 정렬
- 자료를 하나씩 올바른 위치에 삽입하여 정렬하므로 정렬 과정 중 정렬 순번 배열까지 정렬 상태 유지
- 구현이 가장 쉬운 정렬 알고리즘이지만, 효율성은 낮음
| 실행 과정 | 예시 | 8 4 7 3 5 |
| 인접한 두 수를 비교하며 더 큰 값을 뒤로 보내는 과정 반복 한 사이클이 끝나면 가장 큰 수가 뒤로 정렬됨. |
1) 첫 번째와 두 번째 비교 (8 > 4) → 교환 | 4 8 7 3 5 |
| 2) 두 번째와 세 번째 비교 (8 > 7) → 교환 | 4 7 8 3 5 | |
| 3) 세 번째와 네 번째 비교 (8 > 3) → 교환 | 4 7 3 8 5 | |
| 4) 네 번째와 다섯 번째 비교 (8 > 5) → 교환 | 4 7 3 5 8 | |
| 다시 처음부터 반복하며 정렬(전부 정렬될 때까지 반복) | ... |
// python 코드
def bubble_sort(a):
for i in range(len(a) - 1):
for j in range(len(a) - 1 - i):
if a[j] > a[j + 1]:
a[j], a[j + 1] = a[j + 1], a[j]
return a
// C++ 코드
vector<int> bubble_sort(vector<int> a) {
for (int i = 0; i < a.size() - 1; i++) {
for (int j = 0; j < a.size() - 1 - i; j++) {
if (a[j] > a[j + 1]) swap(a[j], a[j + 1]);
}
}
return a;
}
- 삽입 정렬
- 자료를 하나씩 올바른 위치에 삽입하여 정렬하므로 정렬 과정 중 정렬 순번 배열까지 정렬 상태 유지
- 선택정렬보다 시간 효율성 높음. (작은 수를 찾는 과정 X, 수 하나 골라서 앞에서부터 비교)
| 실행 과정 | 예시 | 8 4 7 3 5 |
| 이미 정렬된 배열 부분의 내용과 자신의 값을 비교 → 자신의 위치 찾아 삽입 |
1) 맨 앞자리 수는 이미 정렬된 것으로 봄. | 8 4 7 3 5 |
| 2) 두번째 자리 수 정렬 (4<8 이므로 8 앞에 삽입) | 4 8 7 3 5 | |
| 3) 세번째 자리 수 정렬 (4<7<8 이므로 4와 8 사이에 삽입) | 4 7 8 3 5 | |
| 4) 네번째 자리 수 정렬 (3<4 이므로 4 앞에 삽입) | 3 4 7 8 5 | |
| 5) 다섯번째 자리 수 정렬 (4<5<7 이므로 4와 7 사이에 삽입) | 3 4 5 7 8 |
// python 코드
def insert_sort(a):
for i in range(1, len(a)):
key = a[i]
j = i - 1
while j >= 0 and a[j] > key:
a[j + 1] = a[j]
j -= 1
a[j + 1] = key
return a
// C++ 코드
vector<int> insert_sort(vector<int> a) {
for (int i = 1; i < a.size(); i++) {
int key = a[i];
int j = i - 1;
while (j >= 0 && a[j] > key) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = key;
}
return a;
}
- 퀵 정렬
- 기준(pivot)을 정해 그보다 작은 값은 왼쪽, 큰 값은 오른쪽으로 분할하여 정렬을 반복하는 방식 (분할 정복 방식)
- 선택정렬보다 빠르며, 정렬 알고리즘 중 가장 많이 사용되는 방법 중 하나
- 재귀적으로 정렬을 수행하며 평균 시간복잡도는 매우 우수하지만 최악의 경우(이미 정렬된 경우 등)에는 O(n^2) 시간 발생 가능
| 실행 과정 | 예시 | 8 4 7 3 5 |
| ***기준값(pivot)을 설정 → 이미 정렬된 배열 부분의 내용과 자신의 값을 비교 → 자신의 위치 찾아 삽입 = 재귀적으로 정렬 완료 될 때까지 반복 |
1) 기준값(pivot) 설정 ex) 마지막 요소를 기준으로 설정 | 8 4 7 3 5 |
| 2) 작은 값은 왼쪽, 큰 값은 오른쪽으로 분할 | 4 3 (5 기준) 8 7 | |
| 3) 왼쪽 그룹에 대해 다시 퀵정렬 | [3] 4 (3기준) | |
| 4) 오른쪽 그룹에 대해 다시 퀵정렬 | [7] 8 (7기준) | |
| 5) 전체 정렬 결과 병합 | 3 4 5 7 8 |
***기준값(pivot)을 설정 방법 (첫번째 요소(0), 마지막 요소(n-1), 중간요소(n/2), 무작위, 처음-중간-끝 중 중앙값)
- 합병정렬
- 전체 문제를 한번에 푸는 방식이 아니라 문제를 작은 두개로 분리하고, 다시 반복분리하여 최소에서 문제를 해결하고 그 해결책을 반복적용하여 전체를 해결하는 방식
- 재귀함수 적용시 구현이 용이함. 임시 배열을 이용하는 방식이므로 공간적 낭비 있음.
| 실행 과정 | 예시 ) 8 4 7 3 5 | |||||
| 자료를 두개의 균등한 크기로 분할 → 최소단위까지 반복 → 두 자료를 정렬 기준에 맞게 합병 → 전체 정렬까지 반복 |
![]() |
|||||
- 쉘 정렬
- 자료를 일정 간격(gap)을 두고 나눈 뒤 삽입정렬을 수행하고, 점차 간격을 줄이며 전체 배열을 정렬하는 방식
- 삽입정렬을 개선한 방식으로, 자료 수가 많을수록 효율적
| 실행 과정 | 예시 | 8 4 7 3 5 |
| 자료를 일정 간격으로 나누어 정렬 → 각 그룹 마다 삽입정렬 사용 → 간격을 줄여가며 반복실행 → 간격 1로 줄이고 삽입정렬 수행 |
1) 초기 gap = 2 설정 | 8 4 7 3 5 |
| 2) gap=2로 나눈 그룹 삽입정렬 | 그룹1: (0,2) → 8 7 → 7 4 8 3 5 | |
| 그룹2: (1,3) → 4 3 → 7 3 8 4 5 | ||
| 그룹3: (2,4) → 8 5 → 7 3 5 4 8 | ||
| 3) gap=1로 줄여 전체 삽입정렬 수행 | 3 < 7 → 3 7 5 4 8 | |
| 5 < 7 → 3 5 7 4 8 | ||
| 4 < 7 & 4 < 5 → 3 4 5 7 8 |
- 자료 정렬 알고리즘 선택시 고려사항
- 1) 자료의 양 2) 사용 가능한 기억 공간의 크기 3) 정렬을 위한 자료 이동의 빈도 수
- 효율성을 위한 수행 시간 측정(시간복접도 : 수행시간을 계산하여 알고리즘의 효율성 검토)
| 정렬 알고리즘 종류 | 최선(측정시간 하한 값) | 평균(하한/상한 사이 값) | 최악(측정시간 상한 값) | 비고 |
| 선택정렬 | n^2 | n^2 | n^2 | |
| 버블정렬 | n | n^2 | n^2 | |
| 삽입정렬 | n | n^2 | n^2 | 최선 우수(선택 대비) |
| 빠른(퀵)정렬 | n log n | n log n | n^2 | |
| 합병정렬 | n log n | n log n | n log n | 효율성 우수 |
| 쉘정렬 | n log n | n (log n)^2 | n (log n)^2 | 가장 우수(자료多 유용) |
시간 비효율 : 선택(제일 비효율), 삽입, 버블 -> 단순하고 비효율적
시간 효율 : 빠른, 합병, 쉘(제일 효율) -> 복잡하고 효율적
'이론공부 > 문제해결, 알고리즘' 카테고리의 다른 글
| 다양한 알고리즘 기법 / 단순하게 문제풀기 (1) | 2025.06.21 |
|---|---|
| 자료탐색 알고리즘 (2) | 2025.06.21 |
| 그리디 알고리즘 (0) | 2025.06.21 |
| 문제해결 2 - 자료구조와 문제해결, 논리적사고 기반, 컴퓨팅 사고 기반 (1) | 2025.06.20 |
| 문제해결 1 - 개요, 절차 (1) | 2025.06.17 |
