ํ€ต ์ •๋ ฌ(Quick Sort)๊ณผ ๋“€์–ผ ํ”ผ๋ด‡ ํ€ต ์ •๋ ฌ(Dual Pivot Quick Sort)

ํ€ต ์ •๋ ฌ์˜ ๊ฐœ๋…

์ž„์˜์˜ ํ”ผ๋ด‡(pivot)์„ ๊ธฐ์ค€์œผ๋กœ ํ•ด๋‹น ํ”ผ๋ด‡ ๊ฐ’๋ณด๋‹ค ์ž‘์€ ๋ฐ์ดํ„ฐ๋Š” ํ”ผ๋ด‡์˜ ์™ผ์ชฝ์—, ํฐ ๋ฐ์ดํ„ฐ๋Š” ํ”ผ๋ด‡์˜ ์˜ค๋ฅธ์ชฝ์— ๋ฐฐ์น˜ํ•œ ๋’ค, ์™ผ์ชฝ ๋ถ€๋ถ„๊ณผ ์˜ค๋ฅธ์ชฝ ๋ถ€๋ถ„์„ ๋‹ค์‹œ ํ€ต ์ •๋ ฌ ๋ฐฉ๋ฒ•์œผ๋กœ ์ •๋ ฌํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜

์ „์ฒด ๋ฐ์ดํ„ฐ๋ฅผ 2๊ฐœ์˜ ๋ถ€๋ถ„์œผ๋กœ ๋ถ„ํ• ํ•œ ๋’ค, ๊ฐ๊ฐ์˜ ๋ถ€๋ถ„์„ ๋‹ค์‹œ ํ€ต์ •๋ ฌํ•˜๋Š” ์ „ํ˜•์ ์ธ ๋ถ„ํ• -์ •๋ณต ์•Œ๊ณ ๋ฆฌ์ฆ˜

์›๋ฆฌ

quick_sort(int[] list, int left, int right) {
    if (left < right) {
        int pivot = partition(list, left, right);
        quick_sort(list, left, pivot-1);
        quick_sort(list, pivot+1, right);
    }
}

ํ”ผ๋ด‡์„ ๊ธฐ์ค€์œผ๋กœ ๋ถ„ํ• ํ•˜๊ธฐ

ํ€ต ์ •๋ ฌ ๊ตฌํ˜„์˜ ํ•ต์‹ฌ์€ ์œ„ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ partition()๋ถ€๋ถ„์ธ ์ „์ฒด ๋ฐฐ์—ด์„ ํ”ผ๋ด‡์„ ๊ธฐ์ค€์œผ๋กœ ๋‘ ๋ถ€๋ถ„์œผ๋กœ ๋ถ„ํ• ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๋ถ„ํ• ์˜ ์›๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

QuickSort

  1. ๋ฐฐ์—ด์˜ ์ž„์˜์˜ ์›์†Œ๋ฅผ pivot, ๊ฐ€์žฅ ์ฒซ๋ฒˆ์งธ ์›์†Œ๋ฅผ low, ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰ ์›์†Œ๋ฅผ high์ด๋ผ๊ณ  ์ง€์ •ํ•œ๋‹ค.
  2. low ๊ฐ’์ด pivot ๋ณด๋‹ค ์ž‘์„ ๋™์•ˆ low ์ธ๋ฑ์Šค๋ฅผ ์ฆ๊ฐ€์‹œํ‚จ๋‹ค. ๋ฐ˜๋ณต๋ฌธ์ด ๊ณ„์†๋  ๋•Œ๊นŒ์ง€ ์กฐ๊ฑด์— ๋ถ€ํ•ฉํ•˜๋Š” ์›์†Œ๋“ค์€ pivot์˜ ์™ผ์ชฝ ๋ถ€๋ถ„ ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋œ๋‹ค.
  3. high ๊ฐ’์ด pivot ๋ณด๋‹ค ํด ๋™์•ˆ high ์ธ๋ฑ์Šค๋ฅผ ๊ฐ์†Œ์‹œํ‚จ๋‹ค. ๋ฐ˜๋ณต๋ฌธ์ด ๊ณ„์†๋  ๋•Œ๊นŒ์ง€ ์กฐ๊ฑด์— ๋ถ€ํ•ฉํ•˜๋Š” ์›์†Œ๋“ค์€ pivot์˜ ์˜ค๋ฅธ์ชฝ ๋ถ€๋ถ„ ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋œ๋‹ค.
  4. 2์™€ 3์˜ ๋ฐ˜๋ณต๋ฌธ์„ ํƒˆ์ถœํ•˜์—ฌ ๋„๋‹ฌํ•œ ์œ„์น˜๋Š” ๊ฐ๊ฐ low ๊ฐ’์ด pivot ๋ณด๋‹ค ํฌ๊ณ , high ๊ฐ’์ด pivot ๋ณด๋‹ค ์ž‘์€ ๊ฒฝ์šฐ์ด๋ฏ€๋กœ, ์ด ๋•Œ ๋ฉˆ์ถ˜ ๋‘ ์›์†Œ ์ž๋ฆฌ๋ฅผ ๊ตํ™˜ํ•œ๋‹ค.
  5. low์™€ high์˜ ์œ„์น˜๊ฐ€ ์—‡๊ฐˆ๋ฆฌ์ง€ ์•Š์„ ๋•Œ๊นŒ์ง€ 2~3์˜ ๊ณผ์ •์„ ๋ฐ˜๋ณตํ•œ๋‹ค.
  6. low์™€ high์˜ ์œ„์น˜๊ฐ€ ์—‡๊ฐˆ๋ฆฌ๋Š” ๋•Œ high์™€ pivot์˜ ์ž๋ฆฌ๋ฅผ ๊ตํ™˜ํ•œ๋‹ค. ์ตœ์ข…์ ์œผ๋กœ pivot์˜ ์œ„์น˜๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์™ผ์ชฝ์—๋Š” pivot๋ณด๋‹ค ์ž‘์€ ์›์†Œ๋“ค์ด, ์˜ค๋ฅธ์ชฝ์—๋Š” pivot๋ณด๋‹ค ํฐ ์›์†Œ๋“ค์ด ์œ„์น˜ํ•˜๊ฒŒ ๋œ๋‹ค.

ํ€ต ์ •๋ ฌ ์‹œ๊ฐ„ ๋ณต์žก๋„

  • ๋ถ„ํ•  n๊ฐœ์˜ ์›์†Œ๋ฅผ ๊ฐ€์ง„ ๋ฐฐ์—ด์„ ์ •๋ ฌํ•œ๋‹ค๊ณ  ํ•˜๋ฉด, ๋ฐฐ์—ด์€ ๊ฐ ๋‹จ๊ณ„์—์„œ partition()์„ ๊ฑฐ์น  ๋•Œ๋งˆ๋‹ค n/2, n/4, n/8 โ€ฆ, n/(2^k) ์˜ ํฌ๊ธฐ๋กœ ๋ถ„ํ• ๋œ๋‹ค. ์ด ๊ณผ์ •์€ ๋ฐฐ์—ด์˜ ์›์†Œ ๊ฐœ์ˆ˜๊ฐ€ 1๊ฐœ๊ฐ€ ๋  ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต๋˜๋ฏ€๋กœ n/(2^k) = 1์ผ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต๋œ๋‹ค. ๋”ฐ๋ผ์„œ k = log n๋งŒํผ์˜ ์—ฐ์‚ฐ์ด ์ˆ˜ํ–‰๋œ๋‹ค.
  • ์›์†Œ ๊ตํ™˜ ๊ฐ ์™ผ์ชฝ ๋ถ€๋ถ„์™€ ์˜ค๋ฅธ์ชฝ ๋ถ€๋ถ„์—์„œ๋Š” ๊ตํ™˜์„ ์œ„ํ•ด ๊ฑฐ์˜ ๋ถ€๋ถ„์˜ ๋ชจ๋“  ์›์†Œ๋“ค์„ ํ™•์ธํ•ด์•ผ ํ•˜๋ฏ€๋กœ ๊ฐ ๋ถ€๋ถ„์˜ ์›์†Œ ๊ฐœ์ˆ˜๋งŒํผ(n) ์—ฐ์‚ฐ์ด ์ˆ˜ํ–‰๋œ๋‹ค.

์œ„ ๊ณ„์‚ฐ ๊ฒฐ๊ณผ ์ตœ์ข…์ ์œผ๋กœ ํ‰๊ท  O(n log n)์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋ฅผ ๋ณด์ด๊ฒŒ ๋œ๋‹ค.

ํ•˜์ง€๋งŒ ๋งค๋ฒˆ ๋‹จ ํ•˜๋‚˜์˜ ์›์†Œ๋ฅผ ๊ฐ€์ง„ ๋ถ€๋ถ„์™€ ๋‚˜๋จธ์ง€ ์›์†Œ๋“ค์„ ๊ฐ€์ง„ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋‰˜๋Š” ๊ฒฝ์šฐ ๋“ฑ, ๋ฐฐ์—ด์˜ ์ดˆ๊ธฐ๊ฐ’์ด๋‚˜ ํ”ผ๋ด‡์˜ ์„ ํƒ ๋ฐฉ๋ฒ•์— ๋”ฐ๋ผ ์ตœ์•…์˜ ๊ฒฝ์šฐ O(n^2)์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๋ณด์ผ ์ˆ˜ ์žˆ๋‹ค.

๊ตฌํ˜„

class QuickSort {
    static int left;     // ์™ผ์ชฝ ์ปค์„œ
    static int right;    // ์˜ค๋ฅธ์ชฝ ์ปค์„œ
    static int pivot;    // ํ”ผ๋ด‡

    // ์›์†Œ ๊ตํ™˜
    static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    // ๋ถ„ํ• 
    static void partition(int[] arr, int low, int high) {
        left = low;                     // ์™ผ์ชฝ ์ปค์„œ
        right = high;                   // ์˜ค๋ฅธ์ชฝ ์ปค์„œ
        pivot = arr[(left+right)/2];    // ํ”ผ๋ด‡

        do {
            while(arr[left] < pivot) left++;
            while(arr[right] > pivot) right--;
            if (left <= right) swap(arr, left++, right--);
        } while(left <= right);
    }

    // ํ€ต ์ •๋ ฌ
    static void quickSort(int[] arr, int low, int high) {
        partition(arr, low, high);
        if (low < right) quickSort(arr, low, right);
        if (left < high) quickSort(arr, left, high);
    }
}

๋“€์–ผ ํ”ผ๋ด‡ ํ€ต ์ •๋ ฌ(Dual Pivot Quick Sort)

ํ”ผ๋ด‡ 1๊ฐœ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์‚ผ์•„ ์ •๋ ฌํ•˜๋Š” ํ€ต ์ •๋ ฌ์—์„œ ๋‚˜์•„๊ฐ€ ํ”ผ๋ด‡ 2๊ฐœ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜

์ž„์˜์˜ ํ”ผ๋ด‡ 2๊ฐœ๋ฅผ ๊ธฐ์ค€์œผ๋กœ pivot1 ๋ณด๋‹ค ์ž‘์€ ๋ถ€๋ถ„, pivot1 ~ pivot2 ์‚ฌ์ด์˜ ๋ถ€๋ถ„, pivot2 ๋ณด๋‹ค ํฐ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋ˆˆ ๋’ค ๊ฐ ๋ถ€๋ถ„์„ ๋‹ค์‹œ ๋“€์–ผ ํ”ผ๋ด‡ ํ€ต ์ •๋ ฌ ๋ฐฉ๋ฒ•์œผ๋กœ ์ •๋ ฌํ•œ๋‹ค.

pivot2๋Š” ํ•ญ์ƒ pivot1๋ณด๋‹ค ํฌ๋„๋ก ์„ค์ •ํ•ด์•ผํ•จ์„ ์ฃผ์˜ํ•œ๋‹ค.

Dual Pivot QuickSort

๋“€์–ผ ํ”ผ๋ด‡ ํ€ต ์ •๋ ฌ ์‹œ๊ฐ„ ๋ณต์žก๋„

ํ€ต ์ •๋ ฌ๊ณผ ๋‹ฌ๋ฆฌ 3๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋ˆ„๊ธฐ๋•Œ๋ฌธ์— ฮ˜(nlog3n)์ •๋„์˜ ์—ฐ์‚ฐ์ด ๊ธฐ๋Œ€๋œ๋‹ค. ํ•˜์ง€๋งŒ ์ตœ์•…์˜ ๊ฒฝ์šฐ์—๋Š” ํ€ต ์ •๋ ฌ๊ณผ ๊ฐ™์ด O(n^2)์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ํ”ผํ•  ์ˆ˜ ์—†๋‹ค.