관리 메뉴

Daehyunii's Dev-blog

10 합병 μ •λ ¬ λ³Έλ¬Έ

πŸ“š Language & CS knowledge/Algorithm & Data structure

10 합병 μ •λ ¬

Daehyunii 2022. 8. 7. 23:48

  μ§€κΈˆκΉŒμ§€ κ³΅λΆ€ν–ˆλ˜ 정렬듀은 일반적인 μ •λ ¬ μ•Œκ³ λ¦¬μ¦˜μ΄μ—ˆλ‹€. μ΄μ œλŠ” 보닀 효율적인 μ •λ ¬ μ•Œκ³ λ¦¬μ¦˜λ“€μ— λŒ€ν•œ μ„€λͺ…이닀. 합병 정렬은 μ •ν™•ν•˜κ²Œ λ§ν•˜λ©΄ 뢄해와 합병을 ν•˜λŠ” κ³Όμ •μœΌλ‘œ 정렬이 이뀄진닀. 합병 정렬은 0개의 μš”μ†Œ λ˜λŠ” 1개의 μš”μ†ŒλŠ” 이미 정렬이 λ˜μ–΄μžˆλ‹€λŠ” 것을 ν™œμš©ν•˜λŠ” μ •λ ¬ μ•Œκ³ λ¦¬μ¦˜μ΄λ‹€. 즉 μ •λ ¬λ˜μ–΄ μžˆμ§€ μ•Šμ€ 배열을 μš”μ†Œκ°€ 1개 λ˜λŠ” 0κ°œκ°€ 될 λ•ŒκΉŒμ§€ 배열을 λΆ„ν• ν•œ ν›„ λ‹€μ‹œ μ •λ ¬ν•˜λ©΄μ„œ ν•©λ³‘ν•˜λŠ” 것이닀.(1개 λ˜λŠ” 0개의 μš”μ†Œλ₯Ό κ°€μ§€λŠ” 배열은 이미 정렬이 λ˜μ–΄ μžˆλŠ” 것이기 λ•Œλ¬Έμ΄λ‹€.)

 

  μš°μ„  합병 μ •λ ¬ μ•Œκ³ λ¦¬μ¦˜μ„ κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄μ„œλŠ” μ •λ ¬λ˜μ–΄ μžˆλŠ” 두 배열을 ν•©λ³‘ν•˜λŠ” 방법을 μ•Œμ•„μ•Ό ν•œλ‹€. 

 

10.1 μ •λ ¬λœ 두 λ°°μ—΄ 합병

μ˜μ‚¬μ½”λ“œ

1. μš°μ„  λ°°μ—΄ 두 개λ₯Ό 인수둜 λ°›λŠ” ν•¨μˆ˜λ₯Ό μ •μ˜ν•˜κ³ , λ§ˆμ§€λ§‰μ— λ°˜ν™˜ν•  빈 배열을 λ³€μˆ˜μ— μ €μž₯ν•œλ‹€.

2. 두 λ°°μ—΄μ˜ 인덱슀λ₯Ό 각각 i,j ν¬μΈν„°λ‘œ λ§Œλ“€κ³  λ°˜λ³΅λ¬Έμ„ ν™œμš©ν•œλ‹€.(while문을 μ‚¬μš©ν•˜λŠ”κ²ƒμ΄ μ’‹λ‹€)

3. 인수둜 전달 받은 각 λ°°μ—΄μ˜ 첫 번째 μš”μ†ŒλΆ€ν„° 비ꡐλ₯Ό μ‹œμž‘ν•œλ‹€.

4. 아직 μ‚΄νŽ΄λ³΄μ§€ μ•Šμ€ 값이 μžˆλ‹€λ©΄, 즉 i와 jκ°€ 각각의 λ°°μ—΄ 끝에 λ„λ‹¬ν•˜μ§€ μ•Šμ•˜λ‹€λ©΄, 첫 번째 λ°°μ—΄μ˜ κ°’μœΌλ‘œ 첫 번째 μš”μ†Œλ₯Ό μ·¨ν•œ λ‹€μŒ 두 번째 λ°°μ—΄μ˜ 첫 번째 μš”μ†Œμ™€ λΉ„κ΅ν•œλ‹€. λΉ„κ΅ν•œ μš”μ†Œ 쀑 더 μž‘μ€ 값을 λ³€μˆ˜μ— μ €μž₯ν•œ 빈 배열에 ν• λ‹Ήν•˜κ³  할당을 ν•œ λ°°μ—΄μ˜ 인덱슀 포인터에 1을 λ”ν•˜μ—¬ λ‹€λ₯Έ λ°°μ—΄κ³Ό λ‹€μ‹œ λΉ„κ΅ν•œλ‹€. 그리고 두 λ°°μ—΄μ˜ 길이가 같지 μ•Šμ„ 수 μžˆμœΌλ―€λ‘œ 두 λ°°μ—΄λ‚΄μ˜ 비ꡐ가 λͺ¨λ‘ λλ‚œ ν›„ 아직 λΉ„κ΅ν•˜μ§€ λͺ»ν•œ λ‚˜λ¨Έμ§€ μš”μ†Œλ“€μ„ 빈 배열에 ν• λ‹Ήν•œλ‹€.(이미 λ‹€ 정렬이 λ˜μ–΄ μžˆλŠ” μƒνƒœμ΄κΈ° λ•Œλ¬Έμ— λ‹€ 넣어도 μ •λ ¬λœλ‹€.)

 

function mergeArray(arr1,arr2){
    let results = [];
    let i = 0;
    let j = 0;
    while(i < arr1.length && j < arr2.length){
        if(arr1[i] < arr2[j]){
            results.push(arr1[i]);
            i++;
        }else{
            results.push(arr2[j]);
            j++;
        }
    }

    while(i < arr1.length){  //비ꡐ λ˜μ§€ λͺ»ν•œ λ‚˜λ¨Έμ§€ μš”μ†Œλ“€ μ²˜λ¦¬ν•˜κΈ°
        results.push(arr[i]);
        i++;
    }
    while(j < arr2.length){
        results.push(arr2[j]); //비ꡐ λ˜μ§€ λͺ»ν•œ λ‚˜λ¨Έμ§€ μš”μ†Œλ“€ μ²˜λ¦¬ν•˜κΈ°
        j++;
    }
    return results;
}

  μ΄λ ‡κ²Œ ν•˜λ©΄ 정렬이 λ˜μ–΄ μžˆλŠ” 두 배열을 ν•©λ³‘ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜μ΄ λœλ‹€. μ€‘μš”ν•œκ²ƒμ€ 이미 정렬이 λ˜μ–΄ μžˆλŠ” μƒνƒœμ˜ 배열이어야 μ •λ ¬λ˜λ©΄μ„œ ν•˜λ‚˜μ˜ 배열을 λ§Œλ“€ 수 μžˆλŠ” 것이닀! κ·Έλ ‡κΈ° λ•Œλ¬Έμ— 합병 μ •λ ¬ μ•Œκ³ λ¦¬μ¦˜μ—μ„œ μ •λ ¬λœ μƒνƒœλ₯Ό λ§Œλ“€κΈ° μœ„ν•΄ λΆ„ν• ν•˜λŠ” 것이닀. 이제 합병 정렬을 κ΅¬ν˜„ν•΄ 보자

 

10.2 합병 μ •λ ¬ κ΅¬ν˜„

  이제 μ •λ ¬λœ 두 배열을 ν•©λ³‘ν•˜λŠ” 방법을 μ•Œμ•˜μœΌλ‹ˆ, 이제 배열을 계속 λ‚˜λˆ„λŠ” μž‘μ—…μ΄ 이뀄져야 ν•œλ‹€. 이 κ²½μš°μ—λŠ” Array.prototype.sliceλ©”μ„œλ“œλ₯Ό μ΄μš©ν•˜λŠ” 것이 μ’‹λ‹€. arr.sliceλ©”μ„œλ“œλŠ” 첫 번째 인수둜 받은 μΈλ±μŠ€λΆ€ν„° 두 번째 인수둜 받은 μΈλ±μŠ€κΉŒμ§€ 배열을 λ³΅μ‚¬ν•˜μ—¬ λ°˜ν™˜ν•΄ μ€€λ‹€. μ—¬κΈ°μ„œ μ€‘μš”ν•œ 것은 λ°°μ—΄μ˜ μš”μ†Œκ°€ 0개 λ˜λŠ” 1개λ₯Ό κ°€μ§ˆλ•ŒκΉŒμ§€ 계속 λ‚˜λˆ μ•Ό ν•œλ‹€λŠ” 것이닀. κ·Έ λ‹€μŒ μ •λ ¬λœ 배열을 ν•©λ³‘ν•˜λŠ” μœ„μ— κ΅¬ν˜„ν•΄ 놓은 mergeArrayν•¨μˆ˜λ₯Ό μ΄μš©ν•˜μ—¬ μ •λ ¬ν•˜λ©΄μ„œ ν•©λ³‘ν•˜λŠ” 것이닀. λŒ€λΆ€λΆ„μ˜ 합병 μ •λ ¬ κ΅¬ν˜„μ‹œ μž¬κ·€κ°€ μ‚¬μš©λ˜κΈ° λ•Œλ¬Έμ— μ΄ν•΄ν•˜λŠ”λ° 어렀움이 μžˆμ„ 수 μžˆμœΌλ‚˜, 천천히 λ”°λΌμ˜€λ©΄ μΆ©λΆ„νžˆ 이해할 수 μžˆλ‹€.

function mergeArray(arr1,arr2){
    let results = [];
    let i = 0;
    let j = 0;
    while(i < arr1.length && j < arr2.length){
        if(arr1[i] < arr2[j]){
            results.push(arr1[i]);
            i++;
        }else{
            results.push(arr2[j]);
            j++;
        }
    }

    while(i < arr1.length){  //비ꡐ λ˜μ§€ λͺ»ν•œ λ‚˜λ¨Έμ§€ μš”μ†Œλ“€ μ²˜λ¦¬ν•˜κΈ°
        results.push(arr[i]);
        i++;
    }
    while(j < arr2.length){
        results.push(arr2[j]); //비ꡐ λ˜μ§€ λͺ»ν•œ λ‚˜λ¨Έμ§€ μš”μ†Œλ“€ μ²˜λ¦¬ν•˜κΈ°
        j++;
    }
    return results;
}








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 mergeArray(left, sright);
}

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

  λ°°μ—΄μ˜ κ°€μš΄λ°λ₯Ό λ‚˜νƒ€λ‚΄λŠ” 포인터λ₯Ό λ§Œλ“€κ³  κ·Έ 포인터λ₯Ό κΈ°μ€€μœΌλ‘œ sliceλ©”μ„œλ“œλ₯Ό ν™œμš©ν•˜μ—¬ 2개의 λ°°μ—΄λ‘œ λΆ„ν•  ν•œ ν›„, κ·Έ λΆ„ν•  된 배열듀을 μž¬κ·€μ μœΌλ‘œ 계속 λΆ„ν• ν•˜κ³  0개 λ˜λŠ” 1개의 μš”μ†Œλ₯Ό κ°€μ§ˆλ•Œ κΉŒμ§€ 계속 λΆ„ν• ν•œλ‹€. 그리고 리턴 κ°’μœΌλ‘œ mergeArrayν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ—¬ μ™Όμͺ½ 였λ₯Έ μͺ½ 배열을 μ •λ ¬ν•˜μ—¬ ν•©λ³‘ν•˜κ³  λ°˜ν™˜ν•˜κ³  λ°˜ν™˜ν•˜κ³  λ°˜ν™˜ν•˜μ—¬ λ§ˆμ§€λ§‰μœΌλ‘œ left에 ν•΄λ‹Ήν•˜λŠ” λ²”μœ„μ˜ μš”μ†Œλ“€μ„ μ •λ ¬μ‹œν‚¨ 배열을 ν• λ‹Ήν•˜κ³ , right에 ν•΄λ‹Ήν•˜λŠ” λ²”μœ„μ˜ μš”μ†Œλ“€μ„ μ •λ ¬μ‹œν‚¨ 배열을 ν• λ‹Ήν•œλ‹€. λ§ˆμ§€λ§‰μœΌλ‘œ 두 배열을 mergeArrayν•¨μˆ˜λ₯Ό 톡해 μ •λ ¬ν•œ ν›„ λ°˜ν™˜ν•˜λŠ” 것이닀.

 

 

'πŸ“š Language & CS knowledge > Algorithm & Data structure' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

13 단일 μ—°κ²° 리슀트  (0) 2022.08.12
11 퀡 μ •λ ¬  (0) 2022.08.08
09 μ‚½μž… μ •λ ¬  (0) 2022.08.07
08 선택 μ •λ ¬  (0) 2022.08.07
07 버블 μ •λ ¬  (0) 2022.08.06