์ •๋ ฌ์•Œ๊ณ ๋ฆฌ์ฆ˜ - Merge Sort (๋ณ‘ํ•ฉ์ •๋ ฌ) | C, Python ์ฝ”๋“œ ๊ตฌํ˜„

    ๋ฐ˜์‘ํ˜•

    ์ถœ์ฒ˜:  https://en.wikipedia.org/wiki/Merge_sort

    ๐Ÿ“ŒMerge Sort ๋ณ‘ํ•ฉ ์ •๋ ฌ

    1. ๋ถ„ํ• (Divide): ์ •๋ ฌํ•˜๊ณ ์ž ํ•˜๋Š” ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ฐ™์€ ํฌ๊ธฐ์˜ 2๊ฐœ์˜ ๋ฆฌ์ŠคํŠธ๋กœ ๋ถ„ํ• ํ•œ๋‹ค.
    2. ์ •๋ณต(Conquer): ๊ฐ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ •๋ ฌํ•˜๊ณ , ๊ฐ ๋ฆฌ์ŠคํŠธ์˜ ํฌ๊ธฐ๊ฐ€ ๋” ๋ถ„ํ•  ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด ์žฌ๊ท€์ ์œผ๋กœ ๋ถ„ํ•  ์ •๋ณต์„ ๋ฐ˜๋ณตํ•œ๋‹ค.
    3. ๊ฒฐํ•ฉ(Combine): ์ •๋ ฌ๋œ ๊ฐ ๋ฆฌ์ŠคํŠธ๋ฅผ ํ•˜๋‚˜์˜ ๋ฆฌ์ŠคํŠธ๋กœ ํ•ฉ์นœ๋‹ค.

     

     

    ๐Ÿ“Œpuedo code ๊ตฌํ˜„

    split

    • ๋งŒ์•ฝ ๋ฆฌ์ŠคํŠธ ๊ฐœ์ˆ˜๊ฐ€ ํ•œ ๊ฐœ์ด๋ฉด ํ•ด๋‹น ๊ฐ’ ๋ฆฌํ„ด
    • ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋ฆฌ์ŠคํŠธ๋ฅผ left์™€ right๋กœ ๋‚˜๋ˆ„๊ธฐ (์žฌ๊ท€์šฉ๋ฒ•์„ ์ด์šฉํ•˜์—ฌ ๋ฆฌ์ŠคํŠธ ๊ฐœ์ˆ˜๊ฐ€ ํ•œ ๊ฐœ๊ฐ€ ๋  ๋•Œ๊นŒ์ง€(๋”์ด์ƒ ์ชผ๊ฐค ์ˆ˜ ์—†์„ ๋•Œ๊นŒ์ง€))
      • left = split(์•ž)
      • right = split(๋’ค)
    • left์™€ right ํ•ฉ์น˜๊ธฐ

    merge

    • ์ •๋ ฌ๋œ ์ˆซ์ž๋“ค์„ ๋„ฃ์„ ๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ (sorted)
    • left์™€ right์˜ ๋น„๊ตํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ๊ฐ์˜ index๋ฅผ ์ €์žฅํ•  ๋ณ€์ˆ˜ ์ƒ์„ฑ (left_index, right_index)
    • while left_index < len(left) or right_index < len(right): (์•„์ง ๋น„๊ตํ•  ๋ฐ์ดํ„ฐ๊ฐ€ ๋‚จ์•„์žˆ์œผ๋ฉด)
      • left๋‚˜ right ๋‘˜ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์ด๋ฏธ ์ˆœํšŒํ•˜์—ฌ ๋น„๊ต๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ๋‹ค๋ฉด ๊ทธ ๋ฐ˜๋Œ€์ชฝ ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋Œ€๋กœ ๋’ค์— ๋„ฃ๊ณ  ํ•ด๋‹น index +1. left, right ๊ฐ๊ฐ์€ ๋ชจ๋‘ ์ •๋ ฌ์™„๋ฃŒ๋œ ๋ฆฌ์ŠคํŠธ์ด๊ธฐ ๋•Œ๋ฌธ
      • left[left_index]๊ฐ€ right[right_index]๋ณด๋‹ค ์ž‘์œผ๋ฉด left[left_index]๋ฅผ sorted์— ์ถ”๊ฐ€
      • right[right_index]๊ฐ€ right[right_index]๋ณด๋‹ค ํฌ๋ฉด right[right_index]๋ฅผ sorted์— ์ถ”๊ฐ€

     

    ๐Ÿ“Œ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ตฌํ˜„(C)

    int sorted[N];
    
    
    void merge(int *list, int left, int mid, int right){
      int i, j, k, l;
      i = left;
      j = mid+1;
      k = left;
    
      while(i<=mid && j<=right){
        if(list[i]<=list[j])
          sorted[k++] = list[i++];
        else
          sorted[k++] = list[j++];
      }
    
      while (i <= mid)
    	  sorted[k++] = list[i++];
    
      while (j <= right)
    	  sorted[k++] = list[j++];
    
      for(l=left; l<=right; l++)
        list[l] = sorted[l];
    }
    
    
    void merge_sort(int *num_arr, int left, int right){
    	int mid;
    	if (left < right) {
    		mid = (left + right) / 2; 
    		merge_sort(num_arr, left, mid);
    		merge_sort(num_arr, mid+1, right);
    		merge(num_arr, left, mid, right);
    	}
    }

    merge_sort()์™€ merge()๊ฐ€ ์žฌ๊ท€์ ์œผ๋กœ ํ˜ธ์ถœ๋˜๋Š” ๊ณผ์ •

     

    ๐Ÿ“Œ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ตฌํ˜„(Python)

    def merge_sort(num_list):
        i, j, k = 0, 0, 0
        if len(num_list) == 1:
            return num_list
    
    
        mid = len(num_list) // 2
        left_list = num_list[:mid]
        right_list = num_list[mid:]
        merge_sort(left_list)
        merge_sort(right_list)
    
        while (i < len(left_list) and j < len(right_list)):
            if (left_list[i] <= right_list[j]):
                num_list[k] = left_list[i]
                i += 1
            else:
                num_list[k] = right_list[j]
                j += 1
            k += 1
    
        while (i < len(left_list)):
            num_list[k] = left_list[i]
            i += 1
            k += 1
    
        while (j < len(right_list)):
            num_list[k] = right_list[j]
            j += 1
            k += 1
    
        return(num_list)

     

    ๐Ÿ“Œ์‹œ๊ฐ„๋ณต์žก๋„

    ๋ณ‘ํ•ฉ ์ •๋ ฌ์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋Š” $O(n log(n))$์ด๋‹ค. ์šฐ์„ , ์ „์ฒด ๋ฐฐ์—ด์„ ์ชผ๊ฐค ์ˆ˜ ์—†์„ ๋•Œ๊นŒ์ง€ ๊ณ„์† ๋ถ„ํ• ํ•˜๋Š” ๊ณผ์ •๊นŒ์ง€ $log(n)$๋ฒˆ์˜ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค. (์ฆ‰, merge_sort() ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ๊ฒƒ์ด $lon(n)$๋ฒˆ์ด๋‹ค.)

    ๊ทธ๋ฆฌ๊ณ  ๊ฐ๊ฐ 2๊ฐœ์˜ ๋ฆฌ์ŠคํŠธ๋กœ ๋ถ„ํ• ๋œ ๋‹จ๊ณ„์—์„œ ๋ณ‘ํ•ฉ์„ ํ•  ๋•Œ, ์กฐ๊ฑด ๋น„๊ต๋ฅผ ํ•˜๋ฉฐ while๋ฌธ์„ ์ด $n$๋ฒˆ ๋Œ๊ฒŒ ๋œ๋‹ค.

    ๋”ฐ๋ผ์„œ ๋ณ‘ํ•ฉ ์ •๋ ฌ์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋Š” $O(n log(n))$์œผ๋กœ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

    ๋ฐ˜์‘ํ˜•

    ๋Œ“๊ธ€