728x90
반응형
퀵 정렬(Quick Sort) 및 병합 정렬(Merge Sort)
퀵 정렬과 병합 정렬은 둘 다 "분할 정복(Divide and Conquer)" 전략을 사용하는 효율적인 정렬 알고리즘입니다. 이 글에서는 퀵 정렬과 병합 정렬의 원리와 구현 방법을 Java와 C로 함께 설명합니다.
퀵 정렬 (Quick Sort)
퀵 정렬은 주어진 배열을 기준 값(pivot)을 기준으로 두 부분으로 나누고, 각각의 부분 배열을 재귀적으로 정렬하는 방법을 사용합니다. 시간 복잡도는 평균적으로 $O(n \log n)$ 이지만, 최악의 경우 $O(n^2)$가 될 수 있습니다. 주로 "in-place"로 정렬이 이루어지기 때문에 메모리 사용이 효율적입니다.
퀵 정렬의 원리
- 배열에서 기준 값을 선택합니다 (일반적으로 첫 번째나 마지막 요소, 또는 중간 값).
- 기준 값을 기준으로 배열을 분할하여 작은 값들은 왼쪽에, 큰 값들은 오른쪽에 배치합니다.
- 분할된 두 부분 배열에 대해 재귀적으로 정렬을 수행합니다.
Java 코드 예제
public class QuickSort {
public static void quickSort(int[] arr, int low, int high) {
if (low < high) {
int pivotIndex = partition(arr, low, high);
quickSort(arr, low, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, high);
}
}
private static int partition(int[] arr, int low, int high) {
int pivot = arr[high];
int i = low - 1;
for (int j = low; j < high; j++) {
if (arr[j] <= pivot) {
i++;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
int temp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = temp;
return i + 1;
}
public static void main(String[] args) {
int[] arr = { 34, 7, 23, 32, 5, 62 };
quickSort(arr, 0, arr.length - 1);
for (int num : arr) {
System.out.print(num + " ");
}
}
}
C 코드 예제
#include <stdio.h>
void quickSort(int arr[], int low, int high);
int partition(int arr[], int low, int high);
void quickSort(int arr[], int low, int high) {
if (low < high) {
int pivotIndex = partition(arr, low, high);
quickSort(arr, low, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, high);
}
}
int partition(int arr[], int low, int high) {
int pivot = arr[high];
int i = low - 1;
for (int j = low; j < high; j++) {
if (arr[j] <= pivot) {
i++;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
int temp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = temp;
return i + 1;
}
int main() {
int arr[] = {34, 7, 23, 32, 5, 62};
int n = sizeof(arr) / sizeof(arr[0]);
quickSort(arr, 0, n - 1);
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
return 0;
}
병합 정렬 (Merge Sort)
병합 정렬은 배열을 반으로 나누어 각각을 정렬한 후, 두 부분을 병합하여 정렬된 배열을 만드는 알고리즘입니다. 시간 복잡도는 항상 $O(n \log n)$을 보장하며, 안정적인 정렬 알고리즘입니다. 그러나 추가적인 메모리 공간이 필요하다는 단점이 있습니다.
병합 정렬의 원리
- 배열을 절반으로 나눕니다.
- 각 절반에 대해 병합 정렬을 재귀적으로 호출합니다.
- 나누어진 배열을 정렬하면서 병합합니다.
Java 코드 예제
public class MergeSort {
public static void mergeSort(int[] arr, int left, int right) {
if (left < right) {
int middle = (left + right) / 2;
mergeSort(arr, left, middle);
mergeSort(arr, middle + 1, right);
merge(arr, left, middle, right);
}
}
private static void merge(int[] arr, int left, int middle, int right) {
int n1 = middle - left + 1;
int n2 = right - middle;
int[] leftArray = new int[n1];
int[] rightArray = new int[n2];
for (int i = 0; i < n1; i++) {
leftArray[i] = arr[left + i];
}
for (int j = 0; j < n2; j++) {
rightArray[j] = arr[middle + 1 + j];
}
int i = 0, j = 0, k = left;
while (i < n1 && j < n2) {
if (leftArray[i] <= rightArray[j]) {
arr[k] = leftArray[i];
i++;
} else {
arr[k] = rightArray[j];
j++;
}
k++;
}
while (i < n1) {
arr[k] = leftArray[i];
i++;
k++;
}
while (j < n2) {
arr[k] = rightArray[j];
j++;
k++;
}
}
public static void main(String[] args) {
int[] arr = { 34, 7, 23, 32, 5, 62 };
mergeSort(arr, 0, arr.length - 1);
for (int num : arr) {
System.out.print(num + " ");
}
}
}
C 코드 예제
#include <stdio.h>
void mergeSort(int arr[], int left, int right);
void merge(int arr[], int left, int middle, int right);
void mergeSort(int arr[], int left, int right) {
if (left < right) {
int middle = left + (right - left) / 2;
mergeSort(arr, left, middle);
mergeSort(arr, middle + 1, right);
merge(arr, left, middle, right);
}
}
void merge(int arr[], int left, int middle, int right) {
int n1 = middle - left + 1;
int n2 = right - middle;
int leftArray[n1], rightArray[n2];
for (int i = 0; i < n1; i++) {
leftArray[i] = arr[left + i];
}
for (int j = 0; j < n2; j++) {
rightArray[j] = arr[middle + 1 + j];
}
int i = 0, j = 0, k = left;
while (i < n1 && j < n2) {
if (leftArray[i] <= rightArray[j]) {
arr[k] = leftArray[i];
i++;
} else {
arr[k] = rightArray[j];
j++;
}
k++;
}
while (i < n1) {
arr[k] = leftArray[i];
i++;
k++;
}
while (j < n2) {
arr[k] = rightArray[j];
j++;
k++;
}
}
int main() {
int arr[] = {34, 7, 23, 32, 5, 62};
int n = sizeof(arr) / sizeof(arr[0]);
mergeSort(arr, 0, n - 1);
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
return 0;
}
정리
퀵 정렬과 병합 정렬은 둘 다 효율적인 정렬 알고리즘으로, 상황에 따라 적합한 알고리즘을 선택하여 사용할 수 있습니다. 퀵 정렬은 평균적으로 빠르고 메모리 사용이 적지만, 최악의 경우 시간이 오래 걸릴 수 있습니다. 병합 정렬은 안정적인 성능을 제공하지만 추가적인 메모리 공간이 필요합니다. Java와 C로 각각 구현해보면서 이들 알고리즘의 동작 원리를 이해하는 데 도움이 되었기를 바랍니다.
728x90
반응형
'알고리즘(Algorithm)' 카테고리의 다른 글
그래프 탐색 알고리즘 DFS(Depth First Search)와 BFS(Breadth First Search) (0) | 2025.01.22 |
---|---|
이진 탐색 트리 (Binary Search Tree, BST) (0) | 2025.01.21 |
재귀 [ Recursion ] 개념 및 예제 (0) | 2025.01.19 |
정렬 알고리즘 - 버블 정렬, 선택 정렬, 삽입 정렬 (0) | 2025.01.18 |
해시 테이블[ Hash Table ] 및 해싱 [ Hashing ] (0) | 2025.01.17 |