병합 정렬은 분할과 병합 단계로 나뉘는데 분할 단계는 시간 복잡도에 포함되지 않는다. 병합 정렬의 시간 복잡도는 worst case, best case 모두 다 O(n log n)이다.
worst case , best case 어떤 경우에도 좋은 성능이 보장된다.
또 중복 값의 위치가 변하지 않는다(stable)
메모리 공간이 필요하다.
분할할 때 데이터 요소의 양만큼 새로운 메모리 공간이 필요하다(not in place)
const divide = (array) => {
if (array.length < 2) {
return array
}
const mid = Math.floor(array.length / 2)
const smallOne = array.slice(0, mid)
const smallTwo = array.slice(mid)
return merge1(divide(smallOne), divide(smallTwo))
}
const merge1 = (smallOne, smallTwo) => {
const sorted = [] //결과 담을 배열이 필요(quick sort에 비해 메모리를 추가적으로 써야 한다)
while (smallOne.length && smallTwo.length) {
smallOne[0] <= smallTwo[0] ? sorted.push(smallOne.shift()) : sorted.push(smallTwo.shift())
}
const output = [...sorted, ...smallOne, ...smallTwo]
return output
}
const numbers = [8, 5, 6, 9, 3, 1, 4, 2, 7, 10]
console.log(divide(numbers))
const numbers = [8, 5, 6, 9, 3, 1, 4, 2, 7, 10];
/*
쪼개고 정렬하고 쪼개고 정렬하고를 반복, 즉 길이가 1인 배열 2개 생기면 그 둘을
비교해서 정렬
1st.
divide( [8, 5, 6, 9, 3, 1, 4, 2, 7, 10] )
left right
[8,5,6,9,3] [1,4,2,7,10]
divide( [8, 5, 6, 9, 3, 1, 4, 2, 7, 10] ) =
merge1( divide([8,5,6,9,3]) , divide([1,4,2,7,10]) )
divide([8,5,6,9,3])완료 후 divide([1,4,2,7,10])실행,
이 둘 다 실행 후 merge1의 인자로 들어가서 최종정렬 된다
2nd.
divide( [8,5,6,9,3])
left right
[8,5] [6,9,3]
divide( [8,5,6,9,3]) = merge1( divide([8,5]), divide([6,9,3]) )
3rd.
divide( [8,5] )
= merge1( divide([8]), divide([5]))=merge1([8],[5])
= [5,8]
left right
[8] [5]
4rd.
merge1( divide([8]), divide([5]) );
merge1( [8] , [5] ) => 5 < 8
sorted = [5] left = [8] right = []
merge1( divide([8]), divide([5]) ) = [5,8](output) -> 정렬 완료
5rd.
divide ([6,9,3]) = merge1( divide([6], divide([9,3] );
left right
[ 6 ] [ 9, 3]
6th.
divide([6])=[6]
7rd.
divide( [9,3] ) =
merge1(divide[9] , divide[3]) =merge1( [9], [3]);
=[3,9](output)
left right
[9] [3]
sorted left right
[3] [9] []
8th.
merge1([6],[3,9]) = [3,6,9]
여기까지 처음 divide( [8,5,6,9,3])완료
...나머지는 같은 것 반복
*/
퀵 정렬
병합 정렬