새소식

FrontEnd/알고리즘 및 코테

[알고리즘 JS] 합병 정렬 (merge sort) 나누고 정복해!

  • -

🐣 합병 정렬


[합병정렬자료](https://cs.slides.com/colt_steele/intermediate-sorting-algorithms)
[sorting](https://visualgo.net/en/sorting?slide=1)
[빅오](https://www.bigocheatsheet.com/)

 

 

설명

  • 기존의 버블,선택,삽입 정렬의 경우 작은 규모에서만 사용. 큰 규모일 경우 시간 오래 걸림 O(n^2)
  • 합병 정렬의 경우 O(n long n)으로 향상 가능
  • 합병 정렬은 합병 + 정렬 조합 (분할, 정렬, 합병 모두 일어남)
  • 0개 요소, 1개 요소 배열이 이미 정렬되어 있다는 점을 활용(예로 만약 숫자 1로만 구성된 배열을 정렬해야 할 경우, 정렬되어 있다는 것을 알고 있음을 활용)
  • 배열을 더 작은 배열로 나누는 방식
  • 분할 정복 알고리즘 (분할하고 정복)
  • 0이나 1 요소 배열이 될 때까지 계속

 

  • [8, 3, 5, 4, 7, 6, 1, 2] 요소 8개
  • 반으로 분할하여 코드 시작
  • 정렬된 배열, 0개나 1개 요소가 있는 배열이 될 때까지 분할하는 것
  • 가장 작은 배열을 만들고서 정렬된 배열을 합칠 때 정렬 반복

 

과정 설명 이전

  • 정렬된 두 배열 합병을 담당할 함수를 먼저 구현
  • 입력 배열 두 개에 있는 모든 요소를 포함하는 것이 중요
  • O(n+m) 시간과 O(n+m) 공간으로 실행
  • n과 m은 함수 첫 번째 배열과, 두 번째 배열 크기
  • n이 아주 커지지만 m은 아주 커지지 않는다면 그냥 O(n+m)
  • O(n)이었다면 선형 시간을 사용한다는 거니까 반복하면서 각 항목을 한 번씩 방문
  • 하지만 O(n+m)이므로 각 배열의 각 항목에 대해 한 번씩 반복하는 것

 

정렬된 두 배열 합병 과정

  • 빈 배열 만듦
  • 입력 두 개 취하는 함수 정의, 마지막 반환할 빈 배열 만듦
  • 각 입력 배열에서 가장 작은 값부터 시작
  • 카운터는 i, j 두 개, 0부터 시작
  • while 루프 사용
  • 아직 살펴보지 않은 값이 있다면, 즉 i와 j가 각각의 배열 끝에 도달하지 않았다면, 첫 번째 배열의 값으로 첫 번째 항목을 취한 다음 두 번째 배열의 첫 번째 항목 값과 비교
  • 첫 번째 항목이 더 작다면 결과 배열에 집어넣은 다음 첫 번째 배열의 다음 항목으로 넘어감
  • 반대로 첫 번째 배열에 있는 항목이 더 크다면 두 번째 배열의 값을 취하여 결과로 넣은 다음 두 번째 배열의 다음 값으로 넘어감
  • 배열 하나를 완료한 다음에는 다른 배열의 남은 값을 모두 넣음
merge([1,10,50], [2,14,99,100])

// [1,10,50]과 [2,14,99,100]
// [] 작은 것부터 넣음
  • 두 배열을 두고 시작
  • [1,10,50]과 [2,14,99,100]을 뒀을 때 i, j는 각각 0부터 시작 (1,2를 말함)
  • 1과 2를 비교하여 더 작은 것을 새 배열에 둠 [1]
  • 그 다음 i는 1로 넘어가고 j는 2
  • 10과 2를 비교 했을 때 2가 더 작기 때문에 새 배열에 2 넣어줌 [1,2]
  • 계속해서 반복하여 [1,2,10,14,50,99,100]

 

🐣 배열 합병 구현


합병정렬의 합병 구현

 

mergeArrays.js

// Merges two already sorted arrays
function merge(arr1, arr2) {
  let results = [];
  let i = 0;
  let j = 0;
  while (i < arr1.length && j < arr2.length) {
    if (arr2[j] > arr1[i]) {
      results.push(arr1[i]);
      i++;
    } else {
      results.push(arr2[j])
      j++;
    }
  }
  while (i < arr1.length) {
    results.push(arr1[i])
    i++;
  }
  while (j < arr2.length) {
    results.push(arr2[j])
    j++;
  }
  return results;
}
merge([100, 200], [1, 2, 3, 5, 6])
  • 위에서 아래 코드의 경우 arr2 배열이 더 길고 i,j 각 비교가 끝남
  • 이럴 때 j의 경우 arr2.lenght 보다 작기 때문에
  • arr2 배열 그대로 넣어주기
  while (j < arr2.length) {
    results.push(arr2[j])
    j++;
  }

 

🐣 합병 정렬 구현


합병정렬의 정렬 구현

  • 합병 정렬 목표는 배열을 계속해서 반으로 나누는 것
  • 배열을 나눌때 slice 사용 0에서 중간 배열로, 중간에서 0으로
  • 재귀하여 계속 호출
  • 기본 케이스는 끝에 도달하여 배열 길이가 1보다 작거나 같아야 함
  • 작은 배열 준비되면 작성해 놓은 합병 함수 사용해 다시 합침 > 전체 배열 길이 돌아갈 때 까지

 

mergeSort.js

// Merge function from earlier
function merge(arr1, arr2){
    let results = [];
    let i = 0;
    let j = 0;
    while(i < arr1.length && j < arr2.length){
        if(arr2[j] > arr1[i]){
            results.push(arr1[i]);
            i++;
        } else {
            results.push(arr2[j])
            j++;
        }
    }
    while(i < arr1.length) {
        results.push(arr1[i])
        i++;
    }
    while(j < arr2.length) {
        results.push(arr2[j])
        j++;
    }
    return results;
}

// Recrusive Merge Sort
function mergeSort(arr){
    if(arr.length <= 1) return arr;
    let mid = Math.floor(arr.length/2);
    let left = mergeSort(arr.slice(0,mid));
    let right = mergeSort(arr.slice(mid));
    return merge(left, right);
}

mergeSort([10,24,76,73])

 

🐣 배열 합병 : 빅오 복잡도


 

  • 공간 복잡도만 O(n)

[시간복잡도]

  • 시간복잡도 O(n log n)
  • log n : 8개 요소가 있으면 2를 3번 곱해서 8 (3번 나눔)
  • 32개 요소 22222
  • n : 각 분할마다, 합병할 때 O(n)번 비교
  • O(log n)은 어디서? 분할하면서 몇번 나누는지
  • O(n) 은 어디서? 비교하고 합병할 때, 비교하는 것
  • 빅오 그래프 살펴보면 O(n log n)도 나쁘진 않음. O(n^)에 비해

O(log n)은 어디서? 분할하면서 몇번 나누는지

 

O(n) 은 어디서? 비교하고 합병할 때, 비교하는 것
빅오 그래프 살펴보면 O(n log n)도 나쁘진 않음. O(n^)에 비해

 

[공간복잡도]

  • 배열이 클수록 합병 정렬에서는 메모리에 더 많은 배열 저장 필요
  • 보통은 시간 복잡도를 신경 쓰지만, 공간복잡도를 고려할 때는 버블 정렬등과 비교했을때 합병 정렬이 더 많은 공간 차지함

합병 정렬 끝! 이전 정렬에 대한 정리글은 아래 참고!

 

 

 

[알고리즘 JS] 버블정렬, 선택정렬, 삽입정렬 개념 및 비교!

🐣 정렬기본 내장 JavaScript 정렬sort()기본 정렬 순서는 문자열 유니코드(Unicode) 코드 포인트(code point)에 따름배열의 모든 항목이 문자열로 변환되고, 해당 문자열의 유니코드 값이 선택되고, 그

haileyham.tistory.com

 

 

[알고리즘 JS] 합병 정렬 (merge sort) 나누고 정복해!

🐣 합병 정렬[합병정렬자료](https://cs.slides.com/colt_steele/intermediate-sorting-algorithms)[sorting](https://visualgo.net/en/sorting?slide=1)[빅오](https://www.bigocheatsheet.com/)  설명기존의 버블,선택,삽입 정렬의 경우

haileyham.tistory.com

 

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.