[c++] ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ฐœ๋…๊ณต๋ถ€ :: ์ •๋ ฌ (ํ€ต ์ •๋ ฌ, ํ•ฉ๋ณ‘ ์ •๋ ฌ)

ํ€ต ์ •๋ ฌ

๊ฐœ๋…

ํ€ต ์ •๋ ฌ์˜ ์„ธ๋ถ€๊ณผ์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

 

pivot์ด๋ผ๋Š” ์š”์†Œ๋ฅผ ์„ ํƒํ•œ ํ›„, pivot์„ ๊ธฐ์ค€์œผ๋กœ ์™ผ์ชฝ์—๋Š” pivot๋ณด๋‹ค ์ž‘์€ ์š”์†Œ๋“ค์„ ๋†“๊ณ  ์˜ค๋ฅธ์ชฝ์—๋Š” pivot๋ณด๋‹ค ํฐ ์š”์†Œ๋“ค์„ ๋†“๋Š”๋‹ค.

 

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

 

 ๋ถ„ํ• ์ด ๋ถˆ๊ฐ€๋Šฅํ•  ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณตํ•˜๋‹ค๋ณด๋ฉด ์ตœ์†Œํ•œ์˜ ์š”์†Œ๋กœ ๋‚˜๋ˆ„์–ด์ง€๊ณ  ์ดํ›„ ์ˆœ์„œ๋Œ€๋กœ ๊ฒฐํ•ฉ์„ ์ง„ํ–‰ํ•œ๋‹ค. ์œ„์˜ ๊ทธ๋ฆผ์—์„œ ์ƒ‰์ด ์น ํ•ด์ ธ์žˆ๋Š” ์š”์†Œ๋“ค์„ ์ˆœ์„œ๋Œ€๋กœ ํ•ฉ์น˜๋ฉด ๋œ๋‹ค.

 

ํ€ต ์ •๋ ฌ์€ ๋ถ„ํ•  ์ •๋ณต ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ค‘ ํ•˜๋‚˜์ด๋‹ค. pivot์œผ๋กœ 2๊ฐœ์˜ ๋ถ€๋ถ„ ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•˜๋Š” ๋ถ„ํ• (Divide) ๊ณผ์ •๊ณผ ๋ถ€๋ถ„ ๋ฐฐ์—ด์„ ์žฌ๊ท€์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋Š” ์ •๋ณต(Conquer) ๊ณผ์ •๊ณผ ์ •๋ ฌ๋œ ๋ถ€๋ถ„ ๋ฐฐ์—ด์„ ํ•ฉ๋ณ‘ํ•˜๋Š” ๊ฒฐํ•ฉ(Combine)๊ณผ์ •์ด ์กด์žฌํ•œ๋‹ค.

 

(๋ถ„ํ•  ์ •๋ณต)

 

๊ตฌํ˜„

์˜์‚ฌ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

function quicksort(left, right):
    pivot := arr[left]
    low := left+1
    high := right

    while low < high:
        pivot๋ณด๋‹ค ํฐ ์š”์†Œ๋ฅผ ๊ฐ€์ง„ index ์ฐพ๊ธฐ => low
        pivot๋ณด๋‹ค ์ž‘์€ ์š”์†Œ๋ฅผ ๊ฐ€์ง„ index ์ฐพ๊ธฐ => high
        arr[low]์™€ arr[high] ๊ตํ™˜

    high์™€ pivot ๊ตํ™˜

end

 

c++๋กœ ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

void quickSort(int* arr, int left, int right) {
    if (right - left <= 1)
        return;

    int pivot = arr[left];
    int low = left+1;
    int high = right-1;
    while (1) {
        while(low<right){
            if (arr[low] > pivot)
                break;
            else
                low++;
        }
        while(high>left){
            if (arr[high] < pivot)
                break;
            else
                high--;
        }
        if (low >= high)
            break;
        swap(arr, low, high);
    }
    swap(arr, left, high);
    quickSort(arr, left, high);
    quickSort(arr, high + 1, right);
}

 

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

์ตœ์„ ๊ณผ ์ตœ์•…์˜ ๊ฒฝ์šฐ๋ฅผ ์ƒ๊ฐํ•ด๋ณด์ž.

 

 ํ€ต ์ •๋ ฌ์—์„œ ์ตœ์„ ์˜ ๊ฒฝ์šฐ๋Š” ๋ถ„ํ• ๋˜๋Š” ๋‘ ๋ถ€๋ถ„ ๋ฆฌ์ŠคํŠธ๊ฐ€ ํฌ๊ธฐ๊ฐ€ ๋น„์Šทํ•  ๋•Œ์ผ ๊ฒƒ์ด๋‹ค. ์ตœ์„ ์˜ ๊ฒฝ์šฐ์—์„œ ๋ฆฌ์ŠคํŠธ์˜ ๊ธธ์ด๊ฐ€ 1/2๋กœ ์ค„์–ด๋“ ๋‹ค๊ณ  ํ–ˆ์„ ๋•Œ, 1์ด ๋˜๊ธฐ๊นŒ์ง€ lgn๋ฒˆ์˜ ๋ถ„ํ• ์ด ํ•„์š”ํ•˜๋‹ค. ๋˜ํ•œ ๊ฐ ๋‹จ๊ณ„๋งˆ๋‹ค ๋ฆฌ์ŠคํŠธ๋“ค์ด low, high๋ฅผ ์›€์ง์ด๋ฉฐ pivot๊ณผ ๋น„๊ตํ•˜๋Š” ํšŸ์ˆ˜๋Š” ํ•ฉ์ณ๋ณด๋ฉด n์— ๋น„๋ก€ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๋น„๊ตํšŸ์ˆ˜๋Š” O(nlgn)์ด๋‹ค. ์ด๋™ ํšŸ์ˆ˜๋Š” ๋น„๊ตํšŸ์ˆ˜์— ๋น„ํ•ด์„œ ์ ์œผ๋ฏ€๋กœ ๊ณ ๋ คํ•˜์ง€ ์•Š๋Š”๋‹ค.

 

ํ•œ ์ชฝ์œผ๋กœ ์น˜์šฐ์น˜๋Š” ์ตœ์•…์˜ ๊ฒฝ์šฐ์—๋Š” pivot๊ณผ ๋‹ค๋ฅธ ๋ชจ๋“  ์š”์†Œ๋ฅผ ๋น„๊ตํ•˜์—ฌ ๊ฐ€์žฅ ํฐ(or ์ž‘์€) ์š”์†Œ๋ฅผ ๊ฑฐ๋ฅด๋Š” ์„ ํƒ ์ •๋ ฌ๊ณผ ๊ฐ™์€ ์–‘์ƒ์„ ๋„๋ฏ€๋กœ ์‹œ๊ฐ„๋ณต์žก๋„๊ฐ€ O(n^2)์ด๋‹ค.

์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ๋ฅผ ๋ง‰๊ธฐ ์œ„ํ•ด pivot์„ ๋žœ๋ค์œผ๋กœ ์ •ํ•˜๊ฑฐ๋‚˜ ์ฃผ์–ด์ง„ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฌด์ž‘์œ„๋กœ ์„ž์€ ํ›„ ์ •๋ ฌ์„ ์ง„ํ–‰ํ•˜๊ธฐ๋„ ํ•œ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ํ‰๊ท  ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” ์–ด๋–ป๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์„๊นŒ? 

 


(ํ•„์š”์—†๋‹ค๋ฉด ์Šคํ‚ตํ•ด๋„ ๋œ๋‹ค.)

์œ„์™€ ๊ฐ™์ด pivot์— ๋Œ€ํ•ด ์™ผ์ชฝ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์š”์†Œ๋“ค์„ ์ •๋ฆฌํ•˜๊ณ  ๋‚˜๋ฉด, ๋ฆฌ์ŠคํŠธ์—์„œ์˜ pivot ์œ„์น˜๊ฐ€ ๋“œ๋Ÿฌ๋‚˜๊ฒŒ ๋˜๋Š”๋ฐ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋‘ ๋ถ„๋ฅ˜๋กœ ๋‚˜๋ˆŒ ์ˆ˜(split) ์žˆ๋‹ค๋Š” ๋œป์—์„œ ์ด๋ฅผ splitpoint๋ผ๊ณ  ํ•œ๋‹ค.

 

$$
A(n) = n-1 + \sum \frac{1}{n}(A(i-1) + A(n-i))
$$

 

splitpoint๊ฐ€ i์ผ ๋•Œ์˜ ๋น„๊ตํšŸ์ˆ˜๋Š” splitpoint๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด ๋‹ค๋ฅธ ์š”์†Œ๋“ค๊ณผ ๋น„๊ตํ•˜๋Š” n-1๋ฒˆ์—๋‹ค๊ฐ€ ์žฌ๊ท€์ ์œผ๋กœ ์™ผ์ชฝ i-1๊ฐœ๋ฅผ ํ€ต ์ •๋ ฌํ•˜๋Š”๋ฐ์— ํ•„์š”ํ•œ ํ‰๊ท  ๋น„๊ตํšŸ์ˆ˜, ์˜ค๋ฅธ์ชฝ n-i๊ฐœ๋ฅผ ํ€ต ์ •๋ ฌํ•˜๋Š”๋ฐ์— ํ•„์š”ํ•œ ํ‰๊ท  ๋น„๊ตํšŸ์ˆ˜๋ฅผ ๋”ํ•œ ๊ฒƒ๊ณผ ๊ฐ™๋‹ค. ๋”ฐ๋ผ์„œ splitpoint๋ฅผ 1๋ถ€ํ„ฐ n๊นŒ์ง€ ์˜ฎ๊ฒจ๊ฐ€๋ฉฐ ํ‰๊ท  ๋น„๊ตํšŸ์ˆ˜๋ฅผ ๋”ํ•˜๊ณ  ๊ฒฝ์šฐ์˜ ์ˆ˜ n์œผ๋กœ ๋‚˜๋ˆ„์–ด์ฃผ๋ฉด ์œ„์™€ ๊ฐ™์€ ์‹์ด ์™„์„ฑ๋œ๋‹ค.

 

$$
\sum_{i=1}^{n}(A(i-1)+A(n-i))
$$


์ด ์‹์€ ํ’€์–ด์“ธ ๊ฒฝ์šฐ์—

์ด๋ฏ€๋กœ


$$
\sum_{i=0}^{n-1}2A(i)
$$


์ด๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์ตœ์ข…์ ์œผ๋กœ


$$
A(n) = n-1 + \sum_{i=0}^{n-1}2A(i)
$$


๋ผ๋Š” ์‹์ด ๋‚˜์˜ค๊ฒŒ ๋˜๋Š”๋ฐ, ์ด ์‹์ด ์ตœ์„ ์˜ ๊ฒฝ์šฐ์— ๊ฐ€๊นŒ์šด์ง€ ์ตœ์•…์˜ ๊ฒฝ์šฐ์— ๊ฐ€๊นŒ์šด์ง€๋ฅผ ์ˆ˜ํ•™์  ๊ท€๋‚ฉ๋ฒ•์œผ๋กœ ํŒ๋‹จํ•ด๋ณด์ž.


๋”ฐ๋ผ์„œ ํ‰๊ท  ์‹œ๊ฐ„๋ณต์žก๋„๋Š” ์ตœ์„ ์˜ ์‹œ๊ฐ„๋ณต์žก๋„์— ๊ฐ€๊นŒ์šด O(nlgn)์ด๋‹ค.

 

ํŠน์ง•

  • ์ฐฐ์Šค ์•คํ„ฐ๋‹ˆ ๋ฆฌ์ฒ˜๋“œ ํ˜ธ์–ด๊ฐ€ ๊ฐœ๋ฐœํ–ˆ๋‹ค.
  • ๋ถˆ์•ˆ์ • ์ •๋ ฌ์ด๋‹ค.
  • ๋น„๊ต ์ •๋ ฌ์ด๋‹ค.
  • ํ‰๊ท ์ ์œผ๋กœ ๊ฐ€์žฅ ๋น ๋ฅธ ์ •๋ ฌ ๋ฐฉ๋ฒ•์ด๋‹ค.
  • ๋ถ„ํ•  ์ •๋ณต ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ–ˆ๋‹ค.
  • ์ดํ›„ ๋‚˜์˜ฌ ํ•ฉ๋ณ‘ ์ •๋ ฌ, ํž™ ์ •๋ ฌ์ด ํ•ญ์ƒ O(nlgn)์ธ ๊ฒƒ์— ๋ฐ˜ํ•ด ํ€ต ์ •๋ ฌ์€ ํ‰๊ท  ์‹œ๊ฐ„๋ณต์žก๋„๊ฐ€ O(nlgn)์ด๋‹ค.

 

 

ํ•ฉ๋ณ‘ ์ •๋ ฌ

๊ฐœ๋…

ํ•ฉ๋ณ‘ ์ •๋ ฌ ๋˜ํ•œ ํ€ต ์ •๋ ฌ๊ณผ ๊ฐ™์ด ๋ถ„ํ•  ์ •๋ณต ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•œ ์ •๋ ฌ์ด๋‹ค. ํ•ฉ๋ณ‘ ์ •๋ ฌ์˜ ์„ธ๋ถ€๊ณผ์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

 

๋จผ์ € ์ฃผ์–ด์ง„ ๋ฐฐ์—ด์„ ๋ถ„ํ• ํ•œ๋‹ค.

 

๋ถ„ํ•  ๋œ ๊ฐ๊ฐ์˜ ์š”์†Œ๋“ค์„ ๋น„๊ตํ•˜์—ฌ ํ•ฉ๋ณ‘(์ •๋ณต)ํ•œ๋‹ค.

 

ํ•ฉ๋ณ‘์˜ ์„ธ๋ถ€ ๊ณผ์ •์€ ์œ„์™€ ๊ฐ™๋‹ค. A, B ๋‘ ๋ฆฌ์ŠคํŠธ๋ฅผ ํ•ฉ๋ณ‘ํ•œ๋‹ค๊ณ  ํ–ˆ์„ ๋•Œ ๊ฐ๊ฐ์˜ ๋ฆฌ์ŠคํŠธ์— ํฌ์ธํ„ฐ๋ฅผ ๋‘”๋‹ค. ํฌ์ธํ„ฐ์˜ ์š”์†Œ๋ฅผ ๋น„๊ตํ•˜์—ฌ ์ž‘์€ ์ˆœ์œผ๋กœ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด C์— ์ €์žฅํ•˜๊ณ , ํ•œ ๋ฐฐ์—ด์˜ ๋ชจ๋“  ์š”์†Œ๋ฅผ ๋ชจ๋‘ ์ €์žฅํ–ˆ๋‹ค๋ฉด ๋‹ค๋ฅธ ๋ฐฐ์—ด์˜ ๋‚จ์€ ์š”์†Œ๋ฅผ C์— ์ €์žฅํ•œ๋‹ค. ์œ„์—์„œ๋Š” A์˜ ์š”์†Œ๊ฐ€ ๋จผ์ € ๋ชจ๋‘ ์ €์žฅ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ ํ›„, B์˜ ๋‚จ์€ ์š”์†Œ๋“ค์„ C์— ์ €์žฅํ–ˆ๋‹ค.

 

๊ตฌํ˜„

์˜์‚ฌ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

function merge(left, mid, right):
    l:=left
    r:=right
    sorted := []
    while l<mid+1 && r<right:
        if arr[l]<arr[r]:
            sorted์— arr[l++] ๋„ฃ๊ธฐ
        else
            sorted์— arr[r++] ๋„ฃ๊ธฐ

    ๋‚จ์€ ๋ฐฐ์—ด sorted์— ๋„ฃ๊ธฐ
    sorted ๋ฐฐ์—ด arr[left,right]์— ์ €์žฅ
end

function mergesort(left, right):
    if left==right:
        return;

    mid:= (left+right)/2
    mergesort(left,mid);
    mergesort(mid+1,right);
    merge(left, mid, right);
end

 

c++๋กœ ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

void merge(int* arr, int left, int mid, int right) { 
    int l = left; int r = mid; 
    int* sorted = (int*)malloc(sizeof(int)*(right - left));
    int index = 0;

    while (l < mid && r < right) {
        if (arr[l] < arr[r])
            sorted[index++] = arr[l++];
        else
            sorted[index++] = arr[r++];
    }

    // ๋‚จ์€ ๋ฐฐ์—ด ๋„ฃ๊ธฐ
    if (l >= mid) {
        // ์™ผ์ชฝ ๋ฐฐ์—ด์„ ๋‹ค ๋„ฃ์—ˆ์œผ๋ฉด
        for (int i = r; i < right; i++)
            sorted[index++] = arr[i];
    }
    else if(r >= right){
        // ์˜ค๋ฅธ์ชฝ ๋ฐฐ์—ด์„ ๋‹ค ๋„ฃ์—ˆ์œผ๋ฉด
        for (int i = l; i < mid; i++)
            sorted[index++] = arr[i];
    }

    // sorted => arr
    for (int i = 0; i < right-left; i++) {
        arr[i+left] = sorted[i];
    }
}

void mergeSort(int* arr, int left, int right) {
    if (right-left<=1) // ์›์†Œ๊ฐ€ ํ•˜๋‚˜์ด๋ฉด return
        return;

    int mid = (int)((left + right) / 2);
    mergeSort(arr, left, mid);
    mergeSort(arr, mid, right);
    merge(arr, left, mid, right);
}

 

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

 ํ•ฉ๋ณ‘ ๋‹จ๊ณ„์—์„œ n๋งŒํผ์˜ ์š”์†Œ๋ฅผ ํ›‘์œผ๋ฉด์„œ ๋น„๊ตํ•˜๊ณ  ํ•ฉ์น˜๋Š” ๊ณผ์ •์„ lgn ๋‹จ๊ณ„๋งŒํผ ๋ฐ˜๋ณตํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๋น„๊ต์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋Š” O(nlgn)์ด๋‹ค. ์ด๋™์€ ๊ธฐ์กด ๋ฐฐ์—ด์—์„œ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์œผ๋กœ ์š”์†Œ๋“ค์„ ์˜ฎ๊ธฐ๋Š” ๊ณผ์ •๊ณผ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์—์„œ ๊ธฐ์กด ๋ฐฐ์—ด๋กœ ์š”์†Œ๋“ค์„ ์˜ฎ๊ธฐ๋Š” ๊ณผ์ •์— ์˜ํ•ด 2n๋ฒˆ ๋ฐœ์ƒํ•˜๊ณ , ์ด๋ฅผ lgn ๋‹จ๊ณ„๋งŒํผ ๋ฐ˜๋ณตํ•˜๋ฏ€๋กœ ์ด๋™์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋Š” O(2nlgn)์ด๋‹ค.

 

 ๋”ฐ๋ผ์„œ ํ•ฉ๋ณ‘ ์ •๋ ฌ์˜ ์ด ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” O(nlgn)์ด๋ฉฐ ์ตœ์•…, ์ตœ์„ , ํ‰๊ท ์—์„œ ํฐ ์ฐจ์ด ์—†์ด ๋น„์Šทํ•˜๋‹ค.

ํ€ต ์ •๋ ฌ๊ณผ ๋น„๊ตํ•ด์„œ ์ƒ๊ฐํ•ด๋ณด๋ฉด ๋ถ„ํ•  ๊ณผ์ •์—์„œ ์ ๋ฆผํ˜„์ƒ ์—†์ด ๊ท ๋“ฑํ•˜๊ฒŒ ๋ถ„๋ฐฐ๋˜๋ฏ€๋กœ ํ•ญ์ƒ ํ€ต ์ •๋ ฌ์˜ ์ตœ์„ ์˜ ๊ฒฝ์šฐ์™€ ๊ฐ™๋‹ค. ์‹์œผ๋กœ ๋‚˜ํƒ€๋‚ด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
$$
O(n) = O(\lceil\frac{n}{2}\rceil)+O(\lfloor\frac{n}{2}\rfloor)+ n-1
$$

 

ํŠน์ง•

  • ํ€ต ์ •๋ ฌ๊ณผ ๋น„๊ตํ•˜์—ฌ ์ตœ์•…์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋„ O(nlgn)์ด๋‹ค.
  • ํ•˜์ง€๋งŒ ๊ณต๊ฐ„๋ณต์žก๋„๊ฐ€ O(n)์œผ๋กœ ํฐ ํŽธ์ด๋‹ค.
  • ์•ˆ์ • ์ •๋ ฌ์ด๋‹ค.
  • ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ ์ƒํƒœ์— ์˜ํ–ฅ์„ ๋œ ๋ฐ›๋Š”๋‹ค.
๋ฐ˜์‘ํ˜•