O(n2) ์คํ์๊ฐ์ ๊ฐ๋ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ ์ธ ๊ฐ์ง์ O(nlogn) ์คํ์๊ฐ์ ๊ฐ๋ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ ๋ ๊ฐ์ง, ๊ทธ๋ฆฌ๊ณ ๊ฐ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ์ ํ์ด์ฌ ์ฝ๋๋ฅผ ์ ๋ฆฌํ๋ค.
๋ชฉ์ฐจ
O(n2) ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ
- Bubble sort
- Selection sort
- Insertion sort
O(nlogn) ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ
- Merge sort
- Quick sort
๋ค์ ์ฌ์ดํธ์์ ๊ฐ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ์ ์๊ฐํ๋ฅผ ํ๋์ ํ์ธํ ์ ์๋ค.
Comparison Sorting Visualization
www.cs.usfca.edu
O(n2) ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ
๋ค์์ ์ธ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ์ swap
ํจ์๋ฅผ ์ฌ์ฉํ๋ค.
def swap(arr, i, j):
temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
Bubble sort

- ํ ๋ฒ ๋ ๋๋ง๋ค ๋ง์ง๋ง ํ๋๊ฐ ์ ๋ ฌ๋๋ฏ๋ก ์์๋ค์ด ๊ฑฐํ์ด ์ฌ๋ผ์ค๋ ๊ฒ์ฒ๋ผ ๋ณด์ฌ ๊ฑฐํ์ ๋ ฌ์ด๋ค.
- ๋ค๋ฅธ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ์ ๋นํด ๋งค์ฐ ๋นํจ์จ์ ์ด์ง๋ง, ์ด๋ฏธ ์ ๋ ฌ๋ ์๋ฃ์์๋ ํ๋ฒ๋ง ๋๋ฉด ๋๊ธฐ ๋๋ฌธ์ ์ต์ ์ ์ฑ๋ฅ์ ๋ณด์ฌ์ค๋ค (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(nlogn) ์๊ณ ๋ฆฌ์ฆ์ ์ฐ๋ค๊ฐ ์ ๋ ฌํด์ผ ํ ๋ถ๋ถ์ด ์์๋๋ ์ฝ์ ์ ๋ ฌ๋ก ์ ํํ๋ ๊ฒ๋ค๋ ์๋ค.
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(nlogn) ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ
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(nlogn)์ด์ง๋ง ์ต์ ์ ๊ฒฝ์ฐ์๋ O(n2)์ด๋ค. 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)
์ฐธ๊ณ ํ ์๋ฃ
๋ฐ์ํ