> 기초/알고리즘
TIL-2024.02.29 - 알고리즘 - 정렬 알고리즘
Janku
2024. 2. 29. 23:07
------- 정렬 알고리즘
설명: 데이터를 특정한 기준에 따라 정렬하는 알고리즘
종류:
- 버블 정렬 (Bubble Sort)
- 선택 정렬 (Selection Sort)
- 삽입 정렬 (Insertion Sort)
- 퀵 정렬 (Quick Sort)
- 합병 정렬 (Merge Sort)
버블 정렬 (Bubble Sort):
- 인접한 두 원소를 비교하여 순서대로 정렬하는 방식.
- 시간 복잡도는 O(n^2)로 비효율적인 알고리즘, 구현이 간단.
- 작은 데이터나 교환 횟수가 적은 경우에 적합.
예제:
function bubbleSort(arr) {
let len = arr.length;
for (let i = 0; i < len; i++) {
for (let j = 0; j < len - 1; j++) {
if (arr[j] > arr[j + 1]) {
let temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
let arr = [64, 34, 25, 12, 22, 11, 90];
console.log(bubbleSort(arr)); // [11, 12, 22, 25, 34, 64, 90]
선택 정렬 (Selection Sort):
- 주어진 리스트에서 최솟값을 선택하여 정렬된 리스트에 추가하는 방식.
- 시간 복잡도는 O(n^2)으로 비효율적, 버블 정렬보다는 성능이 조금 나음.
- 구현이 간단하고 작은 리스트에서 사용하기에 적합.
예제:
function selectionSort(arr) {
let len = arr.length;
for (let i = 0; i < len; i++) {
let min = i;
for (let j = i + 1; j < len; j++) {
if (arr[j] < arr[min]) {
min = j;
}
}
if (min !== i) {
let temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
}
return arr;
}
let arr = [64, 25, 12, 22, 11];
console.log(selectionSort(arr)); // [11, 12, 22, 25, 64]
삽입 정렬 (Insertion Sort):
- 리스트를 정렬된 부분과 정렬되지 않은 부분으로 나누고, 정렬되지 않은 부분의 원소를 정렬된 부분에 삽입.
- 시간 복잡도는 평균적으로 O(n^2), 데이터가 이미 거의 정렬된 경우에는 효율적.
- 데이터가 적은 경우나 거의 정렬된 경우에 유용.
예제:
function insertionSort(arr) {
let len = arr.length;
for (let i = 1; i < len; i++) {
let current = arr[i];
let j = i - 1;
while ((j > -1) && (current < arr[j])) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = current;
}
return arr;
}
let arr = [12, 11, 13, 5, 6];
console.log(insertionSort(arr)); // [5, 6, 11, 12, 13]
퀵 정렬 (Quick Sort):
- 분할 정복(divide and conquer) 알고리즘
- 기준 원소(pivot)를 선택하고, 기준 원소보다 작은 원소는 왼쪽에, 큰 원소는 오른쪽에 위치.
- 재귀적으로 이 과정을 반복하여 정렬을 수행.
- 평균적으로 시간 복잡도는 O(n log n)이며, 효율적인 정렬 알고리즘 중 하나.
예제:
function quickSort(arr) {
if (arr.length <= 1) return arr;
let pivot = arr[0];
let left = [];
let right = [];
for (let i = 1; i < arr.length; i++) {
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat(pivot, quickSort(right));
}
let arr = [38, 27, 43, 3, 9, 82, 10];
console.log(quickSort(arr)); // [3, 9, 10, 27, 38, 43, 82]
주어진 배열: [38, 27, 43, 3, 9, 82, 10]
첫 번째 회차(iteration):
피벗(pivot): 38
left: [27, 3, 9, 10]
right: [43, 82]
정렬된 배열: [27, 3, 9, 10, 38, 43, 82]
두 번째 회차(iteration):
피벗(pivot): 27
left: [3, 9, 10]
right: []
정렬된 배열: [3, 9, 10, 27, 38, 43, 82]
세 번째 회차(iteration):
피벗(pivot): 3
left: []
right: [9, 10]
정렬된 배열: [3, 9, 10, 27, 38, 43, 82]
네 번째 회차(iteration):
피벗(pivot): 9
left: []
right: [10]
정렬된 배열: [3, 9, 10, 27, 38, 43, 82]
다섯 번째 회차(iteration):
피벗(pivot): 10
left: []
right: []
정렬된 배열: [3, 9, 10, 27, 38, 43, 82]
여섯 번째 회차(iteration):
피벗(pivot): 43
left: []
right: [82]
정렬된 배열: [3, 9, 10, 27, 38, 43, 82]
일곱 번째 회차(iteration):
피벗(pivot): 82
left: []
right: []
정렬된 배열: [3, 9, 10, 27, 38, 43, 82]
합병 정렬 (Merge Sort):
- 분할 정복 알고리즘을 기반으로 하며, 리스트를 반으로 나눈 후 각각을 재귀적으로 정렬하고 합병하여 정렬된 리스트를 생성합니다.
- 시간 복잡도는 항상 O(n log n)으로 효율적입니다.
- 퀵 정렬과 달리 데이터의 분포에 영향을 받지 않으므로 안정적입니다.
예제:
function mergeSort(arr) {
if (arr.length <= 1) return arr;
const mid = Math.floor(arr.length / 2);
const left = mergeSort(arr.slice(0, mid));
const right = mergeSort(arr.slice(mid));
return merge(left, right);
}
function merge(left, right) {
let result = [];
let leftIndex = 0;
let rightIndex = 0;
while (leftIndex < left.length && rightIndex < right.length) {
if (left[leftIndex] < right[rightIndex]) {
result.push(left[leftIndex]);
leftIndex++;
} else {
result.push(right[rightIndex]);
rightIndex++;
}
}
return result.concat(left.slice(leftIndex), right.slice(rightIndex));
}
let arr = [38, 27, 43, 3, 9, 82, 10];
console.log(mergeSort(arr)); // [3, 9, 10, 27, 38, 43, 82]