본 시리즈는 프로그래밍 알고리즘의 개념을 정리하고 실습을 진행해보는 시리즈입니다.
단순 정렬(Basic Sorting) 알고리즘은 기본적인 정렬 방식으로, 구현이 간단하고 상대적으로 이해하기 쉽습니다.
단순 정렬 알고리즘은 비교 기반 정렬로, 배열이나 리스트의 요소를 차례로 비교하며 정렬을 수행합니다.
대표적인 단순 정렬 알고리즘으로는 버블 정렬 (Bubble Sort), 선택 정렬 (Selection Sort), 삽입 정렬 (Insertion Sort) 등이 있으며, 이들은 주로 교육용이나 작은 데이터셋에 적합합니다.
실무 관점에서는 이 중에서 가장 중요하다 여겨지는 알고리즘은 삽입 정렬 (Insertion Sort)이라 볼수 있습니다.
- 다양한 프로그래밍 언어에서 일반적으로 작은 길이의 데이터에 대한 표준 정렬 알고리즘으로 가장 많이 쓰이는 방식이기 때문입니다.
저번 포스팅에서는 버블 정렬과 선택 정렬을 다루었고, 이번 포스팅에서 삽입 정렬과 이진 삽입 정렬을 다룰 예정입니다.
삽입 정렬 (Insertion Sort)은 배열을 두 부분으로 나누어, 정렬된 부분과 정렬되지 않은 부분을 점차 확장해나가며 정렬하는 방식입니다.
시간 복잡도:
특징:
Insertion Sort는 다음과 같은 순서로 동작합니다:
동작 예시:
주어진 배열 [9, 2, 1, 5, 4]
을 삽입 정렬로 정렬하는 과정:
2
를 첫 번째 자리 9
와 비교하여 교환import java.util.Arrays;
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;
// 앞의 정렬된 부분에서 key가 들어갈 위치를 찾음
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j]; // 한 칸씩 오른쪽으로 이동
j = j - 1;
}
arr[j + 1] = key; // key를 올바른 위치에 삽입
}
}
public static void main(String[] args) {
int[] arr = {9, 2, 1, 5, 4};
insertionSort(arr);
System.out.println("Sorted array: " + Arrays.toString(arr));
}
}
Java 구현 설명:
출력 예시:
Sorted array: [1, 2, 4, 5, 9]
def insertion_sort(arr):
# 배열의 두 번째 요소부터 시작
for i in range(1, len(arr)):
key = arr[i]
j = i - 1
# key가 들어갈 위치를 찾으며, 정렬된 부분에서 비교
while j >= 0 and arr[j] > key:
arr[j + 1] = arr[j] # 요소들을 한 칸씩 오른쪽으로 이동
j -= 1
arr[j + 1] = key # key를 올바른 위치에 삽입
# 예시 배열
arr = [9, 2, 1, 5, 4]
insertion_sort(arr)
print("Sorted array:", arr)
Python 구현 설명:
출력 예시:
Sorted array: [1, 2, 4, 5, 9]
이진 삽입 정렬 (Binary Insertion Sort)은 삽입 정렬의 변형으로, 요소를 삽입할 위치를 찾기 위해 이진 탐색을 사용하여 비교 횟수를 줄이는 방식입니다.
Binary Insertion Sort는 이진 탐색을 활용하여 삽입할 위치를 찾는 삽입 정렬의 변형 알고리즘입니다.
시간 복잡도:
특징:
Binary Insertion Sort는 다음과 같은 순서로 동작합니다:
동작 예시:
주어진 배열 [9, 2, 1, 5, 4]
을 이진 삽입 정렬로 정렬하는 과정:
2
를 이진 탐색으로 삽입할 위치를 찾아 교환1
을 이진 탐색으로 찾아 앞의 두 요소 사이에 삽입5
를 이진 탐색으로 적절한 위치에 삽입4
를 이진 탐색으로 찾아 알맞은 자리에 삽입import java.util.Arrays;
public class BinaryInsertionSort {
public static void binaryInsertionSort(int[] arr) {
int n = arr.length;
for (int i = 1; i < n; i++) {
int key = arr[i];
int left = 0;
int right = i - 1;
// 이진 탐색으로 삽입 위치 찾기
while (left <= right) {
int mid = (left + right) / 2;
if (arr[mid] > key) {
right = mid - 1;
} else {
left = mid + 1;
}
}
// 삽입 위치까지 배열 요소 이동
for (int j = i - 1; j >= left; j--) {
arr[j + 1] = arr[j];
}
// key를 찾은 위치에 삽입
arr[left] = key;
}
}
public static void main(String[] args) {
int[] arr = {9, 2, 1, 5, 4};
binaryInsertionSort(arr);
System.out.println("Sorted array: " + Arrays.toString(arr));
}
}
Java 구현 설명:
출력 예시:
Sorted array: [1, 2, 4, 5, 9]
def binary_insertion_sort(arr):
# 배열의 두 번째 요소부터 시작
for i in range(1, len(arr)):
key = arr[i]
left = 0
right = i - 1
# 이진 탐색으로 삽입 위치 찾기
while left <= right:
mid = (left + right) // 2
if arr[mid] > key:
right = mid - 1
else:
left = mid + 1
# 삽입 위치까지 배열 요소 이동
for j in range(i - 1, left - 1, -1):
arr[j + 1] = arr[j]
# key를 찾은 위치에 삽입
arr[left] = key
# 예시 배열
arr = [9, 2, 1, 5, 4]
binary_insertion_sort(arr)
print("Sorted array:", arr)
Python 구현 설명:
출력 예시:
Sorted array: [1, 2, 4, 5, 9]
단순 정렬 알고리즘들은 구현이 쉽고 이해하기 간단하지만, 대규모 데이터에서는 비효율적일 수 있습니다.
알고리즘 | 시간 복잡도 (최악, 평균) | 공간 복잡도 | 특징 |
---|---|---|---|
Bubble Sort | 구현이 간단하지만 비교 및 교환이 빈번하게 발생 | ||
Selection Sort | 교환 횟수는 적지만, 비교 횟수는 많음 | ||
Insertion Sort | (최선 ) | 작은 배열이나 이미 정렬된 배열에서 효율적 | |
Binary Insertion | (최선 ) | 이진 탐색을 통해 비교 횟수를 줄이지만, 데이터 이동 비용은 그대로 |
이들 알고리즘은 모두 작은 배열에서의 사용에 적합하며, 대규모 데이터에서는 보다 효율적인 정렬 알고리즘을 사용하는 것이 바람직합니다.
이번 포스팅에서는 삽입 정렬과 이진 삽입 정렬의 개념, 동작 원리, 그리고 Java와 Python에서의 구현을 살펴보았습니다.
이러한 단순 정렬 알고리즘들은 간단한 구조와 직관적인 동작 원리로 인해 학습 목적으로도 많이 사용되며, 작은 크기의 배열에서는 실용적인 선택이 될 수 있습니다. 하지만 대규모 데이터를 처리할 때는 다른 효율적인 정렬 알고리즘을 사용하는 것이 바람직합니다.
다음 포스팅에서는 힙 정렬 (Heap Sort), 트리 정렬 (Tree Sort), 등 트리 데이터 구조를 활용하여 데이터를 정렬하는 방식들을 다루도록 하겠습니다.