[์ •๋ ฌ] Merge Sort

๋ณ‘ํ•ฉ ์ •๋ ฌ์˜ ๊ฐœ๋…

๋ณ‘ํ•ฉ ์ •๋ ฌ ์ˆ˜ํ–‰๋„

๋ณ‘ํ•ฉ ์ •๋ ฌ์ด๋ž€?

ํ•˜๋‚˜์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋‘ ๊ฐœ์˜ ๊ท ๋“ฑํ•œ ํฌ๊ธฐ๋กœ ์ตœ๋Œ€ํ•œ ๋ถ„ํ• ํ•˜๊ณ  ๋ถ„ํ• ๋œ ๋ถ€๋ถ„ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆœ์„œ๋Œ€๋กœ ํ•ฉํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.
๋ถ„ํ• ๋œ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆœ์„œ๋Œ€๋กœ ํ•ฉ์ณ์„œ ๋‹ด๊ธฐ ์œ„ํ•œ ์ž๋ฃŒ๊ตฌ์กฐ๊ฐ€ ์ถ”๊ฐ€์ ์œผ๋กœ ํ•„์š”ํ•˜๋‹ค.
๊ฐ€์žฅ ์ž‘์€ ๋‹จ์œ„๋กœ ์ ˆ๋ฐ˜์”ฉ ์ชผ๊ฐ  ํ›„ ๊ฐ€์žฅ ์ž‘์€ ๋‹จ์œ„๋ถ€ํ„ฐ ๋‹ค์‹œ ํ•ฉ์ณ๋‚˜๊ฐ€๋Š”๋ฐ ์ด ํ•ฉ์ณ๋‚˜๊ฐ€๋Š” ๊ณผ์ •์—์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ •๋ ฌ์ด ๋œ๋‹ค.

Divide and Conquer 

  1. Merge Sort์˜ ํ•ด๊ฒฐ ์ „๋žต
  2. ๋ฌธ์ œ๋ฅผ ์ž‘์€ 2๊ฐœ์˜ ๋ฌธ์ œ๋กœ ๋ถ„๋ฆฌํ•˜๊ณ  ๊ฐ๊ฐ์„ ํ•ด๊ฒฐํ•œ ๋‹ค์Œ, ๊ฒฐ๊ณผ๋ฅผ ๋ชจ์•„์„œ ์›๋ž˜์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ์ „๋žต  
  3. Divide and Conquer ๋ฐฉ์‹์€ ๋Œ€๊ฐœ ์žฌ๊ท€ ํ˜ธ์ถœ์„ ์ด์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•จ

๋™์ž‘ ๋ฐฉ์‹๊ณผ ๊ตฌํ˜„

1. ๋ฐ์ดํ„ฐ๋“ค์„ ์ ˆ๋ฐ˜์œผ๋กœ ๋‚˜๋ˆˆ๋‹ค. (๋ถ„ํ• )

2. ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์žฅ ์ž‘์€ ๋‹จ์œ„๋กœ ๋ถ„ํ•ดํ•œ ํ›„ ๋งจ ๋ฐ‘์—์„œ ๋ถ€ํ„ฐ ์ฐจ๋ก€๋Œ€๋กœ ํ•ฉ๋ณ‘์„ ์ง„ํ–‰ํ•œ๋‹ค. (์ •๋ณต)

    2-1. ๋‘๊ฐœ์˜ ๋ฐฐ์—ด ์ค‘ ํ•˜๋‚˜๋ผ๋„ ์ž์‹ ์˜ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚  ๋•Œ ๊นŒ์ง€ ๋ฐ˜๋ณตํ•œ๋‹ค.

        2-1-1 . ๋‘๊ฐœ๋กœ ๋‚˜๋‰˜์–ด์ง„ ๋ฐฐ์—ด์˜ ์š”์†Œ๋ฅผ ์•ž์—์„œ๋ถ€ํ„ฐ ์ฐจ๋ก€๋Œ€๋กœ ๋น„๊ตํ•œ๋‹ค.

        2-1-2. ์˜ค๋ฆ„์ฐจ์ˆœ ์ •๋ ฌ ๊ธฐ์ค€์œผ๋กœ ๋‘๊ฐœ์˜ ์š”์†Œ ์ค‘ ์ž‘์€ ์š”์†Œ๋ฅผ ๋ณ„๊ฐœ์˜ ๋ฆฌ์ŠคํŠธ์— ์‚ฝ์ž…ํ•œ๋‹ค.

        2-1-3. ์‚ฝ์ž…๋œ ์š”์†Œ๋ฅผ ๊ฐ€์ง„ ๋ฐฐ์—ด์˜ ์ธ๋ฑ์Šค๋ฅผ ๋‹ค์Œ ์นธ์œผ๋กœ ์ด๋™์‹œํ‚จ๋‹ค.

    2-2. ๋‚จ์•„ ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋“ค์„ ๋ฆฌ์ŠคํŠธ์— ๋ชจ๋‘ ์‚ฝ์ž…ํ•œ๋‹ค.

๋‘๊ฐœ์˜ ๋‚˜๋‰˜์–ด์ง„ ๋ฐฐ์—ด์„ ์ˆœ์ฐจ์ ์œผ๋กœ ๋น„๊ตํ•˜์—ฌ ์ •๋ ฌ์ด ๊ฐ€๋Šฅํ•œ ์ด์œ ๋Š” ๋‚˜๋‰˜์–ด์ง„ ๋ฐฐ์—ด์ด ์ด๋ฏธ ์ •๋ ฌ์ด ๋˜์–ด์žˆ๋Š” ์ƒํƒœ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.  

→ Method Stack์€ ํ›„์ž…์„ ์ถœ์ด๋‹ˆ๊นŒ, ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์— ํ˜ธ์ถœ๋œ ๋ฉ”์„œ๋“œ๊ฐ€ ๋จผ์ € ์™„๋ฃŒ๋˜๊ธฐ ๋•Œ๋ฌธ

๊ตฌํ˜„ ์ฝ”๋“œ

    void merge(int left, int right, int mid) {
        int[] buffer = new int[right-left+1];
        int bufferIdx = 0, l = left, r = mid+1;
        while(l <= mid && r <= right) {
            if(numbers[l] < numbers[r]) {
                buffer[bufferIdx++] = numbers[l++];
            }
            else {
                buffer[bufferIdx++] = numbers[r++];
            }
        }

        while(l <= mid) {
            buffer[bufferIdx++] = numbers[l++];
        }

        while(r <= right) {
            buffer[bufferIdx++] = numbers[r++];
        }

        for(int i=left; i<=right; i++) {
            numbers[i] = buffer[i-left];
        }
    }

    void divide(int left, int right) {
        if(left < right) {
            int mid = (left + right)/2;
            divide(left, mid);
            divide(mid+1, right);
            merge(left, right, mid);
        }
    }

 

๋ณ‘ํ•ฉ ์ •๋ ฌ์˜ ์žฅ๋‹จ์ 

์žฅ์  

  1. stable sort ๋ฐฉ๋ฒ•์ด๊ธฐ ๋•Œ๋ฌธ์—, ๋‘ ๊ฐœ์˜ ํ‚ค๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์ •๋ ฌ์„ ์‹œ๋„ํ•  ์ˆ˜ ์žˆ์Œ

๋‹จ์ 

  1. ๋ฐฐ์—ด๋กœ ๊ตฌ์„ฑํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด, ๋ณ„๋„์˜ ์ €์žฅ ๊ณต๊ฐ„์ด ํ•„์š”ํ•จ
  2. ์ž„์‹œ ๋ฐฐ์—ด์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜๋ณต์ ์œผ๋กœ ์˜ฎ๊ฒจ์ค˜์•ผ ํ•˜๋ฉฐ, ์‹ฌ์ง€์–ด ๋ณธ๋ž˜ ๋ฐฐ์—ด๋กœ ๋ณต์‚ฌ๊นŒ์ง€ ํ•ด์•ผํ•˜๋ฏ€๋กœ ๊ฐ’์˜ ์ด๋™์ด ๋งŽ์Œ

๋ณ‘ํ•ฉ ์ •๋ ฌ์˜  ์‹œ๊ฐ„ ๋ณต์žก๋„

์‹œ๊ฐ„ ๋ณต์žก๋„

Recursion Tree๋ฅผ ๊ทธ๋ ธ์„ ๋•Œ Tree์˜ ๋†’์ด(k)๋Š”

n/2^k = 1 ์ด๋ฏ€๋กœ, k = lgn์ด๋‹ค. 

 

Tree์˜ ๊ฐ ์ธต์€ ๋ฐ์ดํ„ฐ ์ˆ˜๊ฐ€ ๋™์ผํ•˜๊ฒŒ n์ด๋ฏ€๋กœ ์‹œ๊ฐ„๋ณต์žก๋„๋Š”

O(n * lgn)์ด๋‹ค. 

 

ํ€ต ์ •๋ ฌ๊ณผ ๋‹ค๋ฅด๊ฒŒ ๋ฌด์กฐ๊ฑด ์ ˆ๋ฐ˜์œผ๋กœ ๋ฐฐ์—ด์„ ๋‚˜๋ˆ„๊ธฐ ๋•Œ๋ฌธ์— ํ‰๊ท , ์ตœ์„ , ์ตœ์•… ๋ชจ๋‘ ๋™์ผํ•˜๊ฒŒ O(nlgn)์ด๋‹ค.

 

ํ€ต์ •๋ ฌ๊ณผ ํ•ฉ๋ณ‘์ •๋ ฌ์˜ ์ฐจ์ด์ 

  1. ํ€ต์ •๋ ฌ : ์šฐ์„  ํ”ผ๋ฒ—์„ ํ†ตํ•ด ์ •๋ ฌ → ์˜์—ญ์„ ์ชผ๊ฐฌ
  2. ํ•ฉ๋ณ‘์ •๋ ฌ : ์˜์—ญ์„ ์ชผ๊ฐค ์ˆ˜ ์žˆ์„ ๋งŒํผ ์ชผ๊ฐฌ → ์ •๋ ฌ