3.1 Sorting - 3.1.5 Quick Sort

2024. 1. 16. 23:01ใ†CS - Roadmap.sh/3. Common Algorithms

CS - 3. Common Algorithms - 3.1. Sorting - 3.1.5 Quick Sort

 

๐Ÿ’กQuick Sort is a divide and conquer algorithm. It picks an element as pivot and partitions the given array around the picked pivot. There are many different versions of quickSort that pick pivot in different ways.

ํ€ต ์ •๋ ฌ์€ ๋ถ„ํ•  ๋ฐ ์ •๋ณต ์•Œ๊ณ ๋ฆฌ์ฆ˜์ž…๋‹ˆ๋‹ค. ์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์š”์†Œ๋ฅผ ํ”ผ๋ฒ—์œผ๋กœ ์„ ํƒํ•˜๊ณ  ์„ ํƒ๋œ ํ”ผ๋ฒ—์„ ์ค‘์‹ฌ์œผ๋กœ ์ฃผ์–ด์ง„ ๋ฐฐ์—ด์„ ๋ถ„ํ• ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ ํ”ผ๋ฒ—์„ ์„ ํƒํ•˜๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋ฒ„์ „์˜ ํ€ต ์ •๋ ฌ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

ํ€ต์ •๋ ฌ(Quick Sort)๋Š” ๋ถ„ํ•  ์ •๋ณต(Divide and Conquer) ๋ฐฉ์‹์˜ ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ž…๋‹ˆ๋‹ค.

์ด ๋ฐฉ๋ฒ•์€ ์ฃผ์–ด์ง„ ๋ฐฐ์—ด์„ ๋‘๊ฐœ์˜ ๋ถ€๋ถ„ ๋ฐฐ์—ด๋กœ ๋ถ„ํ• ํ•˜๊ณ , ๊ฐ๊ฐ์„ ๋ณ„๋„๋กœ ์ •๋ ฌํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

 

ํ€ต ์ •๋ ฌ์˜ ๋™์ž‘ ๊ณผ์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

1. ๋ฐฐ์—ด์—์„œ ํ•˜๋‚˜์˜ ์›์†Œ๋ฅผ ๊ณ ๋ฆ…๋‹ˆ๋‹ค. ์ด๋ฅผ ํ”ผ๋ด‡(pivot)์ด๋ผ ํ•ฉ๋‹ˆ๋‹ค.

2. ํ”ผ๋ด‡๋ณด๋‹ค ์ž‘์€ ์›์†Œ๋“ค์„ ํ”ผ๋ด‡์˜ ์™ผ์ชฝ์œผ๋กœ, ํฐ ์›์†Œ๋“ค์€ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ด๋™์‹œํ‚ต๋‹ˆ๋‹ค.

์ด๋ฅผ ๋ถ„ํ• (partition)์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

3. ๋ถ„ํ• ๋œ ๋‘ ๊ฐœ์˜ ์ž‘์€ ๋ฐฐ์—ด์— ๋Œ€ํ•ด ์žฌ๊ท€์ ์œผ๋กœ ์ด ๊ณผ์ •์„ ๋ฐ˜๋ณตํ•ฉ๋‹ˆ๋‹ค.

 

 

In Python

 

ํŒŒ์ด์ฌ์—์„œ ํ€ต์ •๋ ฌ์„ ๊ตฌํ˜„ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

def quick_sort(arr):
    if len(arr) <= 1:
        return arr
    pivot = arr[len(arr) // 2]
    less = [x for x in arr if x < pivot]
    middle = [x for x in arr if x == pivot]
    greater = [x for x in arr if x > pivot]
    return quick_sort(less) + middle + quick_sort(greater)

 

ํ€ต ์ •๋ ฌ์€ ํ‰๊ท ์ ์œผ๋กœ O(log n) ์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค. 

๊ทธ๋Ÿฌ๋‚˜ ์ตœ์•…์˜ ๊ฒฝ์šฐ (์ด๋ฏธ ์ •๋ ฌ๋œ ๋ฐฐ์—ด ๋“ฑ) ์—๋Š” O(n^2)์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

์ •๋ฆฌ & ํ™œ์šฉ

ํ€ต ์ •๋ ฌ์€ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ์— ๋งค์šฐ ํšจ์œจ์ ์ด๋ฉฐ, ์ž‘์€ ๋ฐฐ์—ด์— ๋Œ€ํ•ด์„œ๋„ ๋น ๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋ฏ€๋กœ ๋‹ค๋ฅธ ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ๊ฒฐํ•ฉํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

์ฃผ์˜ํ•  ์ ์€, ํ”ผ๋ด‡ ์„ ํƒ์— ๋”ฐ๋ผ ์„ฑ๋Šฅ์ด ํฌ๊ฒŒ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ์ค‘๊ฐ„๊ฐ’์„ ํ”ผ๋ด‡์œผ๋กœ ์„ ํƒํ•˜๋ฉด ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.

 

๋˜, ํ€ต ์ •๋ ฌ์€ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ฑฐ์˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Š” ์ •๋ ฌํ•˜๋ ค๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋งค์šฐ ํฐ ๊ฒฝ์šฐ์— ์œ ๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

 

๋”ฐ๋ผ์„œ ํ€ต์ •๋ ฌ์€ ์ผ๋ฐ˜์ ์ธ ๋ชฉ์ ์˜ ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ์ž์ฃผ ์‚ฌ์šฉ ๋˜๋ฉฐ,

ํŠนํžˆ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ œํ•œ์ ์ธ ์ƒํ™ฉ์—์„œ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

Appendix, ํ€ต ์ •๋ ฌ์€ ์™œ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ฑฐ์˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„๊นŒ? (+ in Python)

 

ํ€ต ์ •๋ ฌ์ด ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ฑฐ์˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด '์ œ์ž๋ฆฌ ์ •๋ ฌ(in-place sort)' ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ด๊ธฐ ๋–„๋ฌธ์ž…๋‹ˆ๋‹ค.

์ œ์ž๋ฆฌ ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์ž…๋ ฅ ๋ฐฐ์—ด ์ž์ฒด๋ฅผ ์ •๋ ฌํ•˜์—ฌ ์ •๋ ฌ๋œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, ์ด ๊ณผ์ •์—์„œ ์ถ”๊ณผ์ ์ธ ์ €์žฅ ๊ณต๊ฐ„์„ ํ”ผ๋ฃก๋กœ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

ํ€ต ์ •๋ ฌ์—์„œ๋Š” ํ”ผ๋ฒ—(pivot)์„ ์„ ํƒํ•˜๊ณ , ํ”ผ ๋ฒ—์„ ๊ธฐ์ค€์œผ๋กœ ๋ฐฐ์—ด์„ ๋‘ ๊ฐœ์˜ ๋ถ€๋ถ„ ๋ฐฐ์—ด๋กœ ๋ถ„ํ• ํ•˜๋Š” ๊ณผ์ •์ด ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค.

์ด ๋ถ„ํ•  ๊ณผ์ •์€ ์›๋ž˜์˜ ๋ฐฐ์—ด ๋‚ด์—์„œ ์ง„ํ–‰๋˜๋ฉฐ, ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ถ„ํ• ์ด ์ง„ํ–‰๋œ ํ›„์—๋Š” ๊ฐ ๋ถ€๋ถ„ ๋ฐฐ์—ด์— ๋Œ€ํ•ด ๋™์ผํ•œ ๊ณผ์ •์„ ์žฌ๊ท€์ ์œผ๋กœ ๋ฐ˜๋ณตํ•˜์—ฌ ์ •๋ ฌ์„ ์™„์„ฑํ•ฉ๋‹ˆ๋‹ค.

 

์ด๋ ‡๊ฒŒ ์›๋ž˜์˜ ๋ฐฐ์—ด ๋‚ด์—์„œ ์ง์ ‘ ์›์†Œ๋“ค์˜ ์œ„์น˜๋ฅผ ์ •๋ ฌํ•˜๊ธฐ ๋•Œ๋ฌธ์—,

ํ€ต ์ •๋ ฌ์€ ์ถ”๊ฐ€์ ์ธ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ฑฐ์˜ ํ•„์š”๋กœ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

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

 

def quick_sort(arr):
    if len(arr) <= 1:
        return arr
    pivot = arr[len(arr) // 2]
    less = [x for x in arr if x < pivot]
    middle = [x for x in arr if x == pivot]
    greater = [x for x in arr if x > pivot]
    return quick_sort(less) + middle + quick_sort(greater)

์•„๊นŒ ์œ„์—์„œ ํŒŒ์ด์ฌ์—์„œ ํ€ต์ •๋ ฌ์„ ๊ตฌํ˜„ํ•˜์˜€๋Š”๋ฐ, ์œ„ ์ฝ”๋“œ์—์„œ๋Š”

less, middel, greater ๋ผ๋Š” ํ”ผ๋ฒ—์— ๋”ฐ๋ผ ๋ถ„๋ฅ˜ํ•œ ์ƒˆ๋กœ์šด ๋ฆฌ์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

๋”ฐ๋ผ์„œ ๋ฆฌ์ŠคํŠธ ์ปดํ”„๋ฆฌํ—จ์…˜์„ ์‚ฌ์šฉํ•ด ์ƒˆ๋กœ์šด ๋ฆฌ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค๊ธฐ์— ์ถ”๊ฐ€์ ์ธ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์œ„ ์ฝ”๋“œ๋Š” ํ€ต ์ •๋ ฌ์˜ ์ œ์ž๋ฆฌ(in-place)ํŠน์„ฑ์„ ๋ฒ—์–ด๋‚œ๋‹ค.

 

def partition(nums, low, high):
    # ํ”ผ๋ฒ—์„ ์„ ํƒํ•˜๊ณ , ์ž‘์€ ์›์†Œ์™€ ํฐ ์›์†Œ๋ฅผ ์–‘์ชฝ์œผ๋กœ ๋ถ„ํ• ํ•ฉ๋‹ˆ๋‹ค.
    pivot = nums[(low + high) // 2]
    i = low - 1
    j = high + 1
    while True:
        i += 1
        while nums[i] < pivot:
            i += 1
        j -= 1
        while nums[j] > pivot:
            j -= 1
        if i >= j:
            return j
        # ํ”ผ๋ฒ—์„ ๊ธฐ์ค€์œผ๋กœ ์ž‘์€ ์›์†Œ์™€ ํฐ ์›์†Œ๋ฅผ ๊ตํ™˜ํ•ฉ๋‹ˆ๋‹ค.
        nums[i], nums[j] = nums[j], nums[i]

def quick_sort(nums):
    # ํ€ต ์ •๋ ฌ์˜ ๋„์šฐ๋ฏธ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
    def _quick_sort(items, low, high):
        if low < high:
            # ํ”ผ๋ฒ—์„ ๊ธฐ์ค€์œผ๋กœ ๋ถ„ํ• ๋œ ์ง€์ ์„ ๊ตฌํ•ฉ๋‹ˆ๋‹ค.
            split_index = partition(items, low, high)
            # ๋ถ„ํ• ๋œ ๋‘ ๋ถ€๋ถ„์„ ์žฌ๊ท€์ ์œผ๋กœ ์ •๋ ฌํ•ฉ๋‹ˆ๋‹ค.
            _quick_sort(items, low, split_index)
            _quick_sort(items, split_index + 1, high)
    _quick_sort(nums, 0, len(nums) - 1)

# ํ…Œ์ŠคํŠธ
nums = [9, 7, 5, 11, 12, 2, 14, 3, 10, 6]
quick_sort(nums)
print(nums)  # [2, 3, 5, 6, 7, 9, 10, 11, 12, 14]

์ด ์ฝ”๋“œ๋Š” ํ”ผ๋ฒ—์„ ์„ ํƒํ•˜๊ณ , ๋ฐฐ์—ด ๋‚ด์—์„œ ์ง์ ‘ ์œ„์น˜๋ฅผ ๋ณ€๊ฒฝํ•˜์—ฌ ์ •๋ ฌ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

 

 

๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ํ™•์ธํ•ด๋ณด๋ฉด

120 ๋ฐ”์ดํŠธ๋ฅผ ์›๋ณธ๋ฉ”๋ชจ๋ฆฌ์— ์‚ฌ์šฉํ•˜๊ณ  ์ƒˆ๋กœ์šด ๋ฆฌ์ŠคํŠธ๋“ค์„ ํ™œ์šฉํ•˜๊ธฐ์— ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ถ”๊ฐ€์ ์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

์•„๋ž˜์˜ ์ฝ”๋“œ๋Š” ๋ฆฌ์ŠคํŠธ ๋‚ด๋ถ€์—์„œ ์ •๋ ฌ์„ ํ•˜๊ธฐ์— (In-place sort) ์ถ”๊ฐ€์ ์ธ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ์—†๋‹ค๊ณ  ์ƒ๊ฐ๋ฉ๋‹ˆ๋‹ค.

(์•„์ง ๋ฉ”๋ชจ๋ฆฌ์— ๋Œ€ํ•œ ์ดํ•ด๊ฐ€ ๋ถ€์กฑํ•˜์—ฌ, ์—ฐ์‚ฐ์— ํ•„์š”ํ•œ ๋ฉ”๋ชจ๋ฆฌ๋‚˜ ์ถ”๊ฐ€์ ์ธ ๊ณต๋ถ€ํ›„ ์ถ”๊ฐ€ ์ž‘์„ฑ)

728x90

'CS - Roadmap.sh > 3. Common Algorithms' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

3.2. Recursion - 3.2.1 Tail Recursion  (0) 2024.01.21
3.1. Sorting - 3.1.6 Merge Sort  (0) 2024.01.20
3.1 Sorting - 3.1.4 Heap Sort  (0) 2024.01.15
3.1. Sorting - 3.1.3 Insertion Sort  (0) 2024.01.15
3.1. Sorting - 3.1.2 Selection Sort  (1) 2024.01.14