알고리즘
알고리즘 정리 - 병합정렬
프흐프좋아
2024. 2. 9. 20:00
알고리즘 병합정렬은 배열을 정렬하는 효율적인 알고리즘 중 하나이다.
이 알고리즘은 분할 정복을 이용해서 정렬한다!
(1) 분할 : 배열을 반으로 나눈다. 이 과정은 배열을 작은 단위의 하위 배열로 계속해서 나누는 과정이다.
(2) 정복 : 각 하위 배열을 재귀적으로 정렬한다. 이 정렬은 배열이 충분히 작고 정렬된 상태(length가 1일때까지) 계속 된다.
(3) 병합 : 정렬된 하위 배열들을 병합하여 하나의 정렬된 배열을 만든다.
가장 극악의 상황에서도 O(NlogN)의 상황을 보장하는 알고리즘으로
꽤 효율적인 알고리즘이라고 할 수 있다
첨에는 진짜 무슨 소리인지 몰라서 ㅠㅠ 1시간을 넘도록 뚫어져라 쳐다보다가
재귀 << 를 놓친걸 까먹어서 겨우 이해할 수 있었다
function mergeSort(arr) {
if (arr.length <= 1) {
return arr;
}
const middle = Math.floor(arr.length / 2);
const left = arr.slice(0, middle);
const right = arr.slice(middle);
return merge(mergeSort(left), mergeSort(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++;
}
}
// 왼쪽 배열이나 오른쪽 배열 중 남아있는 요소들을 result 배열에 추가
// (어느 한 배열은 이미 모든 요소를 추가했기 때문에 나머지 배열의 요소들을 모두 추가해도 상관 없음)
return result.concat(left.slice(leftIndex)).concat(right.slice(rightIndex));
}
const arr = [8, 3, 1, 7, 0, 10, 2];
console.log("정렬 전:", arr);
const sortedArr = mergeSort(arr);
console.log("정렬 후:", sortedArr);
처음에 할당받은 배열을 다 length가 1이 될 때 까지 분할한 후에
역으로 병합해 나가면서 최종적으로 정렬된 배열을 리턴하는 로직이다.
그러니까,,
[8, 3, 1, 7, 0, 10, 2] (시작)
↓
[8, 3, 1] [7, 0, 10, 2] (분할)
↓ ↓
[8] [3, 1] [7, 0] [10, 2] (분할)
↓ ↓
[3] [1] [7] [0] [10] [2] (분할)
↓ ↓
[3, 1] [7, 0] [10, 2] (분할 완료 - 정복 시작?)
↓ ↓
[1, 3] [0, 7] [2, 10] (정복)
↓ ↓
[1, 3, 8] [0, 2, 7, 10] (병합)
↓ ↓
[0, 1, 2, 3, 7, 8, 10] (최종 병합)
이런 느낌?
중간에 분할 완료후에 1,3 정렬하고 도대체 8이 어케 튀어나오지 하고
이해를 못했는데 재귀를 생각하니 이해가 가는 코드였다