๐Ÿ”‘ CS/์•Œ๊ณ ๋ฆฌ์ฆ˜

์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ •๋ฆฌ + Python ๊ตฌํ˜„ (Bubble sort, Selection sort, Insertion sort, Merge sort, Quick sort)

๋ณต๋งŒ 2022. 7. 22. 00:25

$O(n^2)$ ์‹คํ–‰์‹œ๊ฐ„์„ ๊ฐ–๋Š” ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์„ธ ๊ฐ€์ง€์™€ $O(n\log n)$ ์‹คํ–‰์‹œ๊ฐ„์„ ๊ฐ–๋Š” ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋‘ ๊ฐ€์ง€, ๊ทธ๋ฆฌ๊ณ  ๊ฐ ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ํŒŒ์ด์ฌ ์ฝ”๋“œ๋ฅผ ์ •๋ฆฌํ–ˆ๋‹ค.

 

๋ชฉ์ฐจ

$O(n^2)$ ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜

  • Bubble sort
  • Selection sort
  • Insertion sort

$O(n\log n)$ ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜

  • Merge sort
  • Quick sort

 

๋‹ค์Œ ์‚ฌ์ดํŠธ์—์„œ ๊ฐ ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์‹œ๊ฐํ™”๋ฅผ ํ•œ๋ˆˆ์— ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

Comparison Sorting Visualization

 

www.cs.usfca.edu

 

 

$O(n^2)$ ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜

๋‹ค์Œ์˜ ์„ธ ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ swap ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

def swap(arr, i, j):
    temp = arr[i]
    arr[i] = arr[j]
    arr[j] = temp

 

Bubble sort

 

https://www.resultswebdev.com/bubble-sort-algorithm/

  • ํ•œ ๋ฒˆ ๋Œ ๋•Œ๋งˆ๋‹ค ๋งˆ์ง€๋ง‰ ํ•˜๋‚˜๊ฐ€ ์ •๋ ฌ๋˜๋ฏ€๋กœ ์›์†Œ๋“ค์ด ๊ฑฐํ’ˆ์ด ์˜ฌ๋ผ์˜ค๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์—ฌ ๊ฑฐํ’ˆ์ •๋ ฌ์ด๋‹ค.
  • ๋‹ค๋ฅธ ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ๋น„ํ•ด ๋งค์šฐ ๋น„ํšจ์œจ์ ์ด์ง€๋งŒ, ์ด๋ฏธ ์ •๋ ฌ๋œ ์ž๋ฃŒ์—์„œ๋Š” ํ•œ๋ฒˆ๋งŒ ๋Œ๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ตœ์„ ์˜ ์„ฑ๋Šฅ์„ ๋ณด์—ฌ์ค€๋‹ค ($O(n)$).
  • ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์ž๋ฃŒ๊ฐ€ ์ •๋ ฌ๋˜์–ด ์žˆ๋Š”์ง€ ์•„๋‹Œ์ง€ ๋ชจ๋ฅธ ์ƒํƒœ์—์„œ ์‚ฌ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์˜๋ฏธ๊ฐ€ ์žˆ์Œ.
def bubbleSort(arr):
    for i in range(len(arr)):
        swapped = False
	
        for j in range(len(arr)-i-1): #0~N-i-1๋ฒˆ์งธ๊นŒ์ง€
            if arr[j] > arr[j+1]: #adjacent ์›์†Œ๋“ค์ด ์ •๋ ฌ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์ •๋ ฌํ•ด์คŒ
                swap(arr, j, j+1)
                swapped = True
	
        if not swapped: #swap์ด ํ•œ iter๋™์•ˆ ํ•œ๋ฒˆ๋„ ๋ฐœ์ƒํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ
            break #์ •๋ ฌ์ด ์™„๋ฃŒ๋จ

 

Selection sort

 

  • Early stopping์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ•ญ์ƒ O(n^2) ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฐ๋‹ค.
def selectionSort(arr):
    for i in range(len(arr)):
        min_index = i
		
        #1. i๋ฒˆ๋ถ€ํ„ฐ ๋๊นŒ์ง€ ๋Œ๋ฉด์„œ ๊ฐ€์žฅ ์ž‘์€ ์›์†Œ๋ฅผ ์ฐพ๋Š”๋‹ค
        for j in range(i+1, len(arr)): 
            if arr[i] < arr[j]:
                min_index = j

        #2. i๋ฒˆ ์ž๋ฆฌ์— ์ฐพ์€ ๊ฐ€์žฅ ์ž‘์€ ์›์†Œ๋ฅผ ๋„ฃ๋Š”๋‹ค
        swap(arr, i, min_index)

 

Insertion sort

  • ๋ฐฐ์—ด์ด ์ž‘์„ ๊ฒฝ์šฐ์— ๋งค์šฐ ํšจ์œจ์ ์ด๋‹ค. ๋”ฐ๋ผ์„œ ๊ณ ์„ฑ๋Šฅ ์•Œ๊ณ ๋ฆฌ์ฆ˜๋“ค ์ค‘์—์„œ๋Š” ๋ฐฐ์—ด์˜ ์‚ฌ์ด์ฆˆ๊ฐ€ ํด๋•Œ๋Š” $O(n\log n)$ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์“ฐ๋‹ค๊ฐ€ ์ •๋ ฌํ•ด์•ผ ํ•  ๋ถ€๋ถ„์ด ์ž‘์„๋•Œ๋Š” ์‚ฝ์ž… ์ •๋ ฌ๋กœ ์ „ํ™˜ํ•˜๋Š” ๊ฒƒ๋“ค๋„ ์žˆ๋‹ค.
def insertionSort(arr):
    for i in range(1, len(arr)):
        for j in range(i, 0, -1): #ํ˜„์žฌ์œ„์น˜์˜ ์™ผ์ชฝ์˜ ๋ชจ๋“  ์›์†Œ์— ๋Œ€ํ•ด ์˜ค๋ฅธ์ชฝ->์™ผ์ชฝ์œผ๋กœ ๊ฐ€๋ฉด์„œ
            if arr[j] < arr[j-1]: #adjacentํ•œ ์›์†Œ๋“ค์„ ์กฐ์‚ฌํ•ด์„œ ์ •๋ ฌ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์ •๋ ฌํ•ด์ค€๋‹ค.
                swap(arr, j, j-1)
            else: #๋งŒ์•ฝ adjacent ํ•œ ์›์†Œ๋“ค์ด ์ •๋ ฌ๋˜์–ด ์žˆ๋Š” ๊ฒฝ์šฐ ๋‚˜๋จธ์ง€๋Š” ๋ชจ๋‘ ์ •๋ ฌ๋˜์–ด์žˆ๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ๋”์ด์ƒ ์กฐ์‚ฌํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.
                break

 

 

$O(n\log n)$ ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜

Merge sort

  • Divide-and-conquer (๋ถ„ํ• ์ •๋ณต) ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ์†ํ•œ๋‹ค.
  • Quick sort๋ณด๋‹ค ์„ฑ๋Šฅ์ด ๋–จ์–ด์ง€๊ณ , ์ถ”๊ฐ€์ ์ธ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜์ง€๋งŒ Stableํ•˜๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค. (์ •๋ ฌ์„ ํ•ด๋„ ๊ฐ™์€ ๊ฐ’์˜ ์•ž๋’ค ์ˆœ์„œ๊ฐ€ ๋ฐ”๋€Œ์ง€ ์•Š์Œ)
def mergeSort(arr):
    if len(arr) > 1:
        #1. Divide
        #์ค‘๊ฐ„์ง€์ ์„ ๊ธฐ์ค€์œผ๋กœ arr์„ ๋‘๊ฐœ๋กœ ๋‚˜๋ˆˆ๋‹ค.
        r = len(arr) // 2
        L = arr[:r]
        R = arr[r:]

        #2. Conquer
        #๊ฐ subarr์„ sortํ•œ๋‹ค.
        mergeSort(L)
        mergeSort(M)

        i = j = k = 0

        #3. Combine
        #๊ฐ subarr์˜ ํ•œ ์›์†Œ์”ฉ ๋น„๊ตํ•˜๋ฉด์„œ ์ž‘์€ ๊ฐ’๋ถ€ํ„ฐ arr์— ์ฑ„์›Œ๋‚˜๊ฐ„๋‹ค.
        while i < len(L) and j < len(R):
            if L[i] < R[j]:
                arr[k] = L[i]
                i += 1
            else:
                arr[k] = R[j]
                j += 1
            k += 1

        #๋งŒ์•ฝ ๋‘˜ ์ค‘ ํ•˜๋‚˜์˜ subarr์˜ ๋๊นŒ์ง€ ๋„๋‹ฌํ–ˆ๋‹ค๋ฉด, ๋‚จ์€ subarr๋กœ arr์„ ๋‹ค ์ฑ„์šด๋‹ค.
        while i < len(L):
            arr[k] = L[i]
            i += 1
            k += 1

        while j < len(R):
            arr[k] = R[j]
            j += 1
            k += 1

 

Quick sort

 

  • ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ divide-and-conquer ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋‹ค.
  • ํ‰๊ท ์ ์ธ ์ƒํ™ฉ์—์„œ ์ตœ๊ณ ์˜ ์„ฑ๋Šฅ์„ ๋‚˜ํƒ€๋‚ด๊ณ , ๋งŽ์€ ์–ธ์–ด์˜ ๊ธฐ๋ณธ ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋ฐ”ํƒ•์œผ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Python์˜ ๊ฒฝ์šฐ stable ์ •๋ ฌ์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— quick sort๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • ํ‰๊ท  ์ˆ˜ํ–‰์‹œ๊ฐ„์€ $O(n\log n)$์ด์ง€๋งŒ ์ตœ์•…์˜ ๊ฒฝ์šฐ์—๋Š” $O(n^2)$์ด๋‹ค. Pivot์˜ ์œ„์น˜์— ์„ฑ๋Šฅ์˜ ์˜ํ–ฅ์„ ๋งŽ์ด ๋ฐ›๋Š”๋‹ค.
  • ๋‹ค์Œ ๊ตฌํ˜„์€ pivot์„ ํ•ญ์ƒ ๋ฐฐ์—ด์˜ ์ฒซ ๋ฒˆ์งธ ์›์†Œ๋กœ ์„ค์ •ํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ธ๋ฐ, ์ด์™ธ์—๋„ pivot์„ ๋žœ๋คํ•œ ์œ„์น˜๋กœ ์„ค์ •ํ•˜๊ฑฐ๋‚˜ (random quick sort), ์ค‘๊ฐ„ ์œ„์น˜์˜ ์›์†Œ๋ฅผ pivot์œผ๋กœ ์žก๋Š” ๋ฐฉ๋ฒ• ๋“ฑ์ด ์žˆ๋‹ค.
def quickSort(arr):
    if len(arr) <= 1:
        return arr

    pivot = arr[0]
    L = []
    R = []

    for data in arr[1:]: #pivot์„ ๊ธฐ์ค€์œผ๋กœ, pivot๋ณด๋‹ค ์ž‘์€ ์›์†Œ๋Š” L์—, ํฐ ์›์†Œ๋Š” R์— ๋„ฃ๋Š”๋‹ค. (divide)
        if data <= pivot:
            L.append(data)
        else:
            R.append(data)

    return quick_sort(L) + [pivot] + quick_sort(R) #L๊ณผ R์„ ์ •๋ ฌํ•˜๊ณ  pivot๊ณผ ํ•ฉ์ฒด (conquer + combine)

 

 

์ฐธ๊ณ ํ•œ ์ž๋ฃŒ

๋ฐ˜์‘ํ˜•