목차
1. 삽입 정렬(Insertion Sort)이란? 용어와 주요 개념
삽입 정렬은 배열을 정렬된 부분과 정렬되지 않은 부분으로 나누어, 정렬되지 않은 요소를 하나씩 정렬된 부분에 "삽입"하며 정렬을 완성하는 알고리즘입니다. 카드 게임에서 손에 든 카드를 순서대로 정리하는 방식과 비슷합니다.
주요 개념
- 비교 기반: 요소 간 비교를 통해 순서를 결정.
- 제자리 정렬(In-place Sorting): 추가 메모리 공간이 거의 필요 없음(공간 복잡도 O(1)).
- 안정 정렬(Stable Sorting): 동일한 값의 상대적 순서가 유지됨.
- 시간 복잡도: 최악과 평균은 O(n²), 최선은 O(n).
특징
- 적응적(Adaptive): 이미 정렬된 데이터에서는 매우 빠름.
- 온라인 알고리즘: 데이터가 실시간으로 들어와도 처리 가능.
- 단순함: 코드가 간단하고 이해하기 쉬움.
2. 삽입 정렬 예시와 코드 설명
예시: 배열 [5, 2, 9, 1, 5] 정렬
삽입 정렬은 두 번째 요소부터 시작해 앞의 정렬된 부분에 삽입합니다. 단계별로 살펴보겠습니다.
단계별 진행
- [5] → 정렬된 상태.
- [5, 2] → 2를 5 앞에 삽입 → [2, 5].
- [2, 5, 9] → 9는 이미 적절한 위치 → [2, 5, 9].
- [2, 5, 9, 1] → 1을 앞쪽으로 삽입 → [1, 2, 5, 9].
- [1, 2, 5, 9, 5] → 두 번째 5를 삽입 → [1, 2, 5, 5, 9].
public class InsertionSort {
public static void insertionSort(int[] arr) {
int n = arr.length;
for (int i = 1; i < n; i++) {
int key = arr[i]; // 삽입할 요소
int j = i - 1; // 정렬된 부분의 마지막 인덱스
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j]; // 요소를 오른쪽으로 이동
j--;
}
arr[j + 1] = key; // key를 적절한 위치에 삽입
}
}
public static void main(String[] args) {
int[] arr = {5, 2, 9, 1, 5};
insertionSort(arr);
System.out.println("정렬된 배열: " + Arrays.toString(arr));
}
}
- key: 현재 삽입할 요소.
- while 루프: key보다 큰 요소를 오른쪽으로 이동.
- 삽입: key를 적절한 위치에 배치.
3. 삽입 정렬 관련 질문 & 풀이
질문 1: "역순으로 정렬된 배열 정렬"
문제: 역순으로 정렬된 배열을 삽입 정렬로 오름차순 정렬하라.
입력: [5, 4, 3, 2, 1]
출력: [1, 2, 3, 4, 5]
풀이 : 삽입 정렬은 역순 배열(최악의 경우)에서도 잘 작동합니다.
public class ReverseSorted {
public static void insertionSort(int[] arr) {
int n = arr.length;
for (int i = 1; i < n; i++) {
int key = arr[i];
int j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
}
public static void main(String[] args) {
int[] arr = {5, 4, 3, 2, 1};
insertionSort(arr);
System.out.println("정렬된 배열: " + Arrays.toString(arr)); // 출력: [1, 2, 3, 4, 5]
}
}
- 역순 배열은 삽입 정렬의 최악의 경우(O(n²)).
- 각 요소가 정렬된 부분의 맨 앞으로 이동하며 비교 횟수가 최대화됨.
질문 2: "부분 배열 정렬"
문제: 배열의 특정 구간만 삽입 정렬로 정렬하라.
입력: [3, 7, 1, 4, 6], 시작 인덱스 1, 끝 인덱스 3
출력: [3, 1, 4, 7, 6]
풀이 : 지정된 구간에 대해 삽입 정렬을 적용합니다.
public class PartialInsertionSort {
public static void partialInsertionSort(int[] arr, int start, int end) {
for (int i = start + 1; i <= end; i++) {
int key = arr[i];
int j = i - 1;
while (j >= start && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
}
public static void main(String[] args) {
int[] arr = {3, 7, 1, 4, 6};
int start = 1, end = 3;
partialInsertionSort(arr, start, end);
System.out.println("정렬된 배열: " + Arrays.toString(arr)); // 출력: [3, 1, 4, 7, 6]
}
}
- start와 end로 구간을 제한.
- 구간 내에서만 삽입 정렬 수행.
- 시간 복잡도: O((end - start)²).
질문 3: 삽입 정렬과 선택 정렬의 차이점을 설명하고, 각각 어떤 경우에 더 적합한가요?
답변:
- 삽입 정렬: 이미 정렬된 부분에 새로운 요소를 삽입하는 방식으로 정렬합니다. 안정 정렬이며, 거의 정렬된 배열에서 효율적입니다.
- 선택 정렬: 배열에서 가장 작은 요소를 선택하여 현재 위치와 교환하는 방식으로 정렬합니다. 불안정 정렬이며, 데이터 교환 횟수가 적습니다.
적합한 경우:
- 삽입 정렬: 데이터가 거의 정렬되어 있거나, 데이터가 스트리밍 방식으로 입력될 때 (온라인 정렬)
- 선택 정렬: 데이터 교환 비용이 매우 큰 경우 (메모리 쓰기 횟수를 최소화해야 하는 경우)
4. 실무 코딩에서 삽입 정렬 적용 예시
삽입 정렬은 소규모 데이터나 이미 거의 정렬된 데이터를 다룰 때 실무에서 유용합니다.
- 작은 데이터 세트 정렬: 데이터베이스 쿼리 결과가 작을 때, 삽입 정렬을 사용하여 빠르게 정렬할 수 있습니다.
- 점진적인 데이터 정렬: 새로운 데이터가 지속적으로 추가될 때, 삽입 정렬을 사용하여 기존 데이터를 유지하면서 새로운 데이터를 정렬된 상태로 삽입할 수 있습니다.
예시: 주문 내역 정렬
Spring Boot에서 주문 날짜순으로 소규모 주문 목록을 정렬:
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
public List<Order> getSortedOrders() {
List<Order> orders = orderRepository.findTop10ByOrderByIdDesc(); // 최근 10개 주문 조회
for (int i = 1; i < orders.size(); i++) {
Order key = orders.get(i);
int j = i - 1;
while (j >= 0 && orders.get(j).getOrderDate().isAfter(key.getOrderDate())) {
orders.set(j + 1, orders.get(j));
j--;
}
orders.set(j + 1, key);
}
return orders;
}
}
- 소규모 데이터(10개 이하)라면 삽입 정렬이 충분히 빠름.
- 이미 거의 정렬된 경우(예: 최근 주문) 성능이 O(n)에 가까워짐.
5. 삽입 정렬의 주의사항
장점
- 적응적: 정렬된 데이터에서 O(n)으로 매우 효율적.
- 안정성: 동일 값의 순서 유지.
- 간단함: 구현이 쉬워 소규모 작업에 적합.
단점
- 시간 복잡도: 최악의 경우 O(n²)로 대규모 데이터에 부적합.
- 비교 횟수: 데이터가 역순일 때 비효율적.
- 실무 제한: 대규모 데이터에서는 퀵 정렬, 병합 정렬 등이 더 적합.
5. 결론
삽입 정렬은 소규모 데이터나 거의 정렬된 데이터에서 빛을 발하는 알고리즘입니다. 코딩 테스트와 학습용으로 적합하며, 코딩 테스트에서는 기본 개념을 묻는 문제에 자주 등장하며, 실제 개발에서는 특정 조건 하에서 유용하게 활용될 수 있습니다. 삽입 정렬의 장단점을 이해하고, 상황에 맞는 적절한 알고리즘을 선택하는 것이 중요합니다.
'이직&취업 > 알고리즘' 카테고리의 다른 글
너비 우선 탐색(BFS): 개념부터 실무 적용까지 (30) | 2025.04.05 |
---|---|
병합 정렬(Merge Sort) 완벽 분석: 개념부터 실무 적용까지 (29) | 2025.04.05 |
선택 정렬(Selection Sort) 완벽 분석: 코딩 테스트부터 실무 활용까지! (27) | 2025.04.04 |
버블 정렬 (Bubble Sort): 개념부터 실전 코딩까지 완벽 가이드 (25) | 2025.04.03 |
깊이 우선 탐색(DFS): 알고리즘 개념부터 실전 코딩까지 완벽 가이드 (25) | 2025.04.03 |