description |
---|
์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ ๊ฐ๋
์ ๋ฆฌ |
- ๋จ์ํ์ง๋ง, ์กฐ๊ธ ๋๋ฆฐ ์ ๋ ฌ
- Bubble sort
- Insertion sort
- Selection sort
- ์กฐ๊ธ ๋ณต์กํ์ง๋ง, ๋น ๋ฅธ ์ ๋ ฌ
- Quick sort
- Merge sort
- Heap sort
- ๊ธฐํ
- Radix sort
- ๊ฐ์ฅ ์์ ๊ฐ์ ์ฐพ๋๋ค.
- ์ฐพ์ ๊ฐ์ ๋ฐฐ์ด์ ๋งจ ์ ์์์ ๊ต์ฒดํ๋ค.
- ์ ๋ ฌ์ ์ํํ ์์๋ฅผ ์ ์ธํ๊ณ , 1๋ฒ 2๋ฒ ๊ณผ์ ์ ๋ชจ๋ ๋ฐ๋ณตํ๋ค.
- ์ต์ , ์ต์ , ํ๊ท ์ ์๊ฐ๋ณต์ก๋๊ฐ ๋ค๋ฅด์ง ์๋ค.
- ๋ฐ์ดํฐ ์์์ ๊ด๊ณ ์์ด ๋ชจ๋ ์์์ ๋ํด ๋น๊ต ์ฐ์ฐ์ ์ํํ๊ธฐ ๋๋ฌธ์ด๋ค.
- ์๊ฐ๋ณต์ก๋๋
$$O(n^2)$$ - 1๋ฒ ๊ณผ์ ์์ for loop๊ฐ n-1ํ ๋ฐ๋ณตํ๋ค.
- 2๋ฒ ๊ณผ์ ์์ ๊ฐ์ฅ ์์ ์๋ฅผ ์ฐพ๊ธฐ ์ํด ๋จ์ ์์๊ณผ ๋น๊ตํ๋ค : n-1, n-2...
- 3๋ฒ ๊ณผ์ ์ ๊ตํ์ ์์ ์๊ฐ์ ์์ ์ด๋ค.
$$T(n) = (n-1) + (n-2) + ... + 2 + 1 = \frac{n(n+1)}{2} = O(n^2)$$
func selectionSort(_ array: inout [Int]) {
for current in 0 ..< array.count - 1 {
var minIndex = current
for index in current+1 ..< array.count {
if array[index] < array[minIndex] {
minIndex = index
}
}
array.swapAt(minIndex, current)
}
}
var array = [10, 2, 33, 20, 7]
selectionSort(&array)
print(array)
{% hint style="info" %} ์ ์ผ ํฐ ๊ฐ์ ์์๋ฅผ ์ฐพ์ ์์น๋ฅผ ๊ฒฐ์ ํ ํ ๋ค์ ์์๋ฅผ ํ์ํ๋ค๋ ์ ์์ Selection Sort์ ๋น์ทํ๋ค.
ํ์ง๋ง ์ต๋๊ฐ์ ์ฐพ๊ณ , ๋ง์ง๋ง ์์น๋ก ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ์์ ์ฐจ์ด๊ฐ ์กด์ฌํ๋ค. {% endhint %}
- ์ฒซ๋ฒ์งธ ์ธ๋ฑ์ค๋ถํฐ ๋ค์ ์ธ๋ฑ์ค์์ ๊ฐ์ ๋น๊ตํ๋ค.
- ๋ง์ฝ, ๋ค์ ์ธ๋ฑ์ค์ ์ ์ฅ๋ ๊ฐ๋ณด๋ค, ํ์ฌ ์ธ๋ฑ์ค ๊ฐ์ด ๋ ํฌ๋ค๋ฉด, ์๋ฆฌ๋ฅผ ๊ตํํ๋ค.
- ๋ง์ง๋ง ์์๊น์ง ๋น๊ต๊ฐ ๋๋๋ค๋ฉด, ์ ์ผ ๋ง์ง๋ง ์์์๋ ๋ฐฐ์ด ์ค ๊ฐ์ฅ ํฐ ๊ฐ์ด ์ ์ฅ๋์ด ์์ ๊ฒ์ด๋ค.
- ํด๋น ๊ณผ์ ์ ๋ชจ๋ ๋ฐฐ์ด์ด ์ ๋ ฌ๋ ๋๊น์ง ๋ฐ๋ณตํ๋ค.
- ์ฝ์ ์ ๋ ฌ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ์ต์ , ์ต์ , ํ๊ท ์๊ฐ๋ณต์ก๋๊ฐ ๋์ผํ๋ค.
- ๋ฐ์ดํฐ์ ์์์ ์๊ด ์์ด ๋ชจ๋ ์์์ ๋ํด ๋น๊ต ์ฐ์ฐ์ ์ํํ๊ธฐ ๋๋ฌธ์ด๋ค.
- ์๊ฐ๋ณต์ก๋ =
$$O(n^2)$$ - ์ฒซ ๋ฒ์งธ for loop์์ n-1๋ฒ์ ๋ฐ๋ณต์ ํตํด ๊ฐ๊ฐ์ ์์น๋ฅผ ์ฐพ์๋๊ฐ๋ค.
- ๋ ๋ฒ์งธ for loop์์ index์ ๋ํด ๊ฐ ์ธ์ ์์๋ฅผ ํ์ํ๊ฒ ๋๋ค. (n-1, n-2, ..1)
- ๊ตํ ์ฐ์ฐ์ ์์ ์๊ฐ์ด ์์๋๋ค.
$$T(n) = (n-1) + (n-2) + ... + 2 + 1 = \frac{n(n+1)}{2} = O(n^2)$$
func bubbleSort(_ array: inout [Int]) {
for i in 0 ..< array.count {
var isSwap = false
for j in 0 ..< array.count - i - 1 {
if array[j] > array[j+1] {
array.swapAt(j, j+1)
isSwap = true
}
}
// ํ์ฌ ๋ฐ๋ณต๋ฌธ์์ ํ ๋ฒ๋ swap์ด ๋ํ๋์ง ์์๋ค๋ฉด, ์ด๋ฏธ ๋ชจ๋ ์ ๋ ฌ๋ ๊ฒ์ด๋ค.
guard isSwap else { return }
}
}
var array = [10, 2, 33, 20, 7]
bubbleSort(&array)
print(array)
{% hint style="info" %} ๋ฐฐ์ด์ ์์๋ฅผ ํ๋์ฉ ์ถ๊ฐํ๋ฉฐ ํด๋น ์์์ ์์น๋ฅผ ๊ฒฐ์ ํ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
์ ๋ ฌ๋ K-1 ๊ฐ์ ๋ฐฐ์ด์ ๋ํด {% endhint %}
- ์ด ๊ณผ์ ์ i ๋ฒ์งธ ์์๋ฅผ ์ฝ์ ํ๊ธฐ ์ํ ๊ณผ์ ์ด๋ผ๊ณ ์๊ฐํ์.
- i ๋ฒ์งธ ์์๋ฅผ ์์ ๋ณ์์ ์ ์ฅํ๋ค.
- i-1 ๋ฒ์งธ๋ถํฐ 1๋ฒ์งธ๊น์ง ๋ฐ๋ณตํ๋ฉฐ, ์์ ๋ณด๋ค ํฌ๊ธฐ๊ฐ ์์ ์์๊ฐ ๋์ฌ ๋ ๊น์ง ๋ฐ๋ณตํ๋ฉฐ ํด๋น ์์์ ์์น๋ฅผ ์ฐพ์ ์ ์ฅํ๋ค.
- for loop๋ n-1 ๋ฒ ๋ฐ๋ณตํ๋ค.
- ์ฝ์ ์ ๊ฒฝ์ฐ, ์ต์ ์ ๊ฒฝ์ฐ i-1 ๋ฒ ๋น๊ตํ๊ฒ ๋๋ค.
- ์ต์
์ ๊ฒฝ์ฐ ์๊ฐ๋ณต์ก๋๋
$$O(n^2)$$ - ์ญ์์ผ๋ก ์ ๋ ฌ๋์ด์๋ ๊ฒฝ์ฐ, ๋งค๋ฒ i-1ํ ํ์ํด์ผํ๋ค.
- ์ต์ ์ ๊ฒฝ์ฐ ์๊ฐ๋ณต์ก๋๋
$$O(n)$$ - ์ฒ์๋ถํฐ ๋ฐฐ์ด์ด ์ ๋ ฌ๋์ด์๋ ๊ฒฝ์ฐ, 1๋ฒ์ ๋น๊ต๋ก ํด๋น ์์์ ์์น๊ฐ ๊ฒฐ์ ๋ ์ ์๋ค.
var array = [10, 2, 33, 20, 7]
insertionSort(&array)
print(array)
func insertionSort(_ array: inout [Int]) {
for i in 1 ..< array.count {
for j in stride(from: i, to: 0, by: -1) {
guard array[j] < array[j-1] else { continue }
array.swapAt(j, j-1)
}
}
}
- merge sort์ quick sort์์ ๊ณตํต์ผ๋ก ์ฌ์ฉ๋๋ ๊ธฐ๋ฒ์ด๋ค. (๋ณธ์ง์ ์ผ๋ก recursion์ ์ฌ์ฉํ๋ค)
- 3๊ฐ์ง ๋จ๊ณ๋ก ๊ฑฐ์ณ๋ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๊ฒ
- ๋ถํ : ํด๊ฒฐํ๊ณ ์ ํ๋ ๋ฌธ์ ๋ฅผ ์์ ํฌ๊ธฐ์ ๋์ผํ ๋ฌธ์ ๋ค๋ก ๋ถํ ํ๋ค.
- ์ ๋ณต : ๊ฐ๊ฐ์ ์์ ๋ฌธ์ ๋ฅผ ์ํ์ ์ผ๋ก ํด๊ฒฐํ๋ค. (๋์ผํ ๋ฌธ์ ๋ค๋ก ๋ถํ ๋๋ฏ๋ก, ์์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ํน์ํ ์๊ณ ๋ฆฌ์ฆ์ด ์๊ตฌ๋์ง ์๋๋ค. ์ฆ, ์ต์ข ๋ฌธ์ ํด๊ฒฐ ์๊ณ ๋ฆฌ์ฆ๊ณผ ์์ ๋ฌธ์ ํด๊ฒฐ ์๊ณ ๋ฆฌ์ฆ์ด ๋์ผํ๋ค. )
- ํฉ๋ณ : ์ ๋ฌธ์ ์ ํด๋ฅผ ํฉํ์ฌ ์๋ ๋ฌธ์ ์ ๋ํ ํด๋ฅผ ๊ตฌํ๋ค.
-
๋ฐ์ดํฐ๊ฐ ์ ์ฅ๋ ๋ฐฐ์ด์ ์ ๋ฐ์ผ๋ก ๋๋๋ค.
-
๊ฐ๊ฐ์ ์ํ์ ์ผ๋ก ์ ๋ ฌํ๋ค.
๊ธธ์ด๊ฐ 1์ธ ๋ฆฌ์คํธ๋ก ๋๋์ด์ง ๊ฒ์ด๋ค.
-
์ ๋ ฌ๋ ๋ ๊ฐ์ ๋ฐฐ์ด์ ํฉ์ณ ์ ์ฒด๋ฅผ ์ ๋ ฌํ๋ค. (์ด ๋ถ๋ถ์ ๊ตฌํ์ด ํ์ํ๋ค)
๊ธธ์ด๊ฐ 1์ธ ๋ฆฌ์คํธ๋ฅผ ํฉ์น๋ ๊ณผ์ ์์ ์ ๋ ฌ์ ์ํํด์ผํ๋ค.
- ๋ฐ์ผ๋ก ๋๋ ๋ฆฌ์คํธ๋ฅผ ํฉ์น ๋ ์ฐ์ฐ์ด ์กด์ฌํ๋ค.
- ๋ฆฌ์คํธ๋ฅผ ๋ฐ์ผ๋ก ๋๋๋ ํ์ = log(N)์ด๋ค. (ํธ๋ฆฌ์ ๋์ด ์๊ฐ)
- ํฉ์น ๋ n ๋งํผ์ ํ์๊ฐ ์์๋๋ค.
- ๋ฐ๋ผ์ ์๊ฐ๋ณต์ก๋๋
$$O(N) = NlogN$$
mergeSort(A[], p, r) { // A[p...r]์ ์ ๋ ฌํ๋ค.
if (p < r) then {
q <- (p+q)/2
mergeSort(A, p, q)
merge(A, p, q, r)
}
}
merge(A[], p, q, r) {
์ ๋ ฌ๋์ด์๋ ๋ ๋ฐฐ์ด A[p...q], A[q+1...r]์ ํฉํ์ฌ
์ ๋ ฌ๋ ๋ฐฐ์ด A[p...r]์ ๋ง๋ ๋ค.
}
func mergesort(_ array: [Int]) -> [Int] {
guard array.count > 1 else { return array }
let center = array.count / 2
let left = Array(array[0..<center])
let right = Array(array[center..<array.count])
func merge(_ left: [Int], _ right: [Int]) -> [Int] {
var left = left
var right = right
var result = [Int]()
while !left.isEmpty && !right.isEmpty {
if left[0] < right[0] {
result.append(left.removeFirst())
} else {
result.append(right.removeFirst())
}
}
return result + left + right
}
return merge(mergesort(left), mergesort(right))
}
func mergeSort(array: [Int]) -> [Int] {
guard array.count > 1 else { return array }
let center = array.count / 2
let leftArray = mergeSort(array: Array(array[0..<center]))
let rightArray = mergeSort(array: Array(array[center..<array.count]))
return merge(left: leftArray, right: rightArray)
}
func merge(left: [Int], right: [Int]) -> [Int] {
var leftIndex = 0
var rightIndex = 0
var result = [Int]()
while leftIndex < left.count, rightIndex < right.count {
if left[leftIndex] < right[rightIndex] {
result.append(left[leftIndex])
leftIndex += 1
} else {
result.append(right[rightIndex])
rightIndex += 1
}
}
if leftIndex < left.count {
result += Array(left[leftIndex ..< left.count])
} else {
result += Array(right[rightIndex ..< right.count])
}
return result
}
{% hint style="info" %} ๋ถํ ์ ๋ณต๋ฒ์ ์ฌ์ฉํ๋ค. (๋ฐ์ดํฐ ๋ถํ ๋ฐฉ๋ฒ์์ Merge Sort์ ์ฐจ์ด๊ฐ ์๋ค.)
ํน์ ๊ฐ์ ๊ธฐ์ค์ผ๋ก ๋ถํ ํ๋ค. (์ต์ ์ ๊ฒฝ์ฐ ์๊ฐ ๋ณต์ก๋๋ ๋์ผํ๋ค) {% endhint %}
- Quick sort์ ๋ถํ ์์๋ ๋ฐ์ผ๋ก ๋ถ๋ฆฌ๋๋ค๋ ๋ณด์ฅ์ด ์๋ค.
- ์ต์ ์ ๊ฒฝ์ฐ๋ pivot์ด ๋ฆฌ์คํธ์์ ๊ฐ์ฅ ํฐ ๊ฐ์ด๊ฑฐ๋, ๊ฐ์ฅ ์์ ๊ฐ์ธ ๊ฒฝ์ฐ์ด๋ค.
- ๋ถํ ํ Pivot ์์๋ pivot๋ณด๋ค ์๊ณ , ๋ค๋ ํฌ๋ค.
- ๋ถํ ๋จ๊ณ์์ ์ ๋ ฌ์ด ์ํ๋๊ธฐ ๋๋ฌธ์ ํฉ๋ณ ๋จ๊ณ์์ ํน๋ณํ ์๊ณ ๋ฆฌ์ฆ์ด ์๊ตฌ๋์ง ์๋๋ค.
quicksort(A[], p, r) {
if (p < r) then
q = partition(A, p, r) // ๋ถํ , q๋ pivot์ ์์น
quicksort(A, p, q-1) // ์ผ์ชฝ ๋ถ๋ถ ๋ฐฐ์ด ์ ๋ ฌ
quicksort(A, q+1, r) // ์ค๋ฅธ์ชฝ ๋ถ๋ถ ๋ฐฐ์ด ์ ๋ ฌ
}
}
partition(A[], p, r) {
๋ฐฐ์ด A[p...r]์ ์์๋ค์ A[r]์ ๊ธฐ์ค์ผ๋ก ์์ชฝ์ผ๋ก ์ฌ๋ฐฐ์นํ๊ณ ,
A[r]์ด ์๋ฆฌํ ์์น๋ฅผ ๋ฆฌํดํ๋ค. // ํผ๋ด์ ์์น๋ฅผ ๋ฆฌํดํ๋ค.
}
func quickSort(_ array: [Int]) -> [Int] {
guard array.count > 1 else { return array }
var array = array
let pivot = array.removeLast()
let left = array.filter { $0 < pivot }
let right = array.filter { $0 >= pivot }
return quickSort(left) + [pivot] + quickSort(right)
}
{% hint style="info" %} ํ ์ ๋ ฌ์ ์ต๋ ํ์ด๋ ์ต์ ํ์ ๊ตฌ์ฑํ์ฌ ์ ๋ ฌํ๋ ๋ฐฉ๋ฒ์ด๋ค.
- ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ : ์ต๋ํ
- ์ค๋ฆ์ฐจ์ ์ ๋ ฌ : ์ต์ ํ {% endhint %}
- ์ฃผ์ด์ง ๋ฐ์ดํฐ๋ฅผ heap์ผ๋ก ๋ง๋ ๋ค.
- ํ์์ ์ต๋๊ฐ๊ณผ ๋ง์ง๋ง ๋ฆฌํ๋ ธ๋์ ์๋ฆฌ๋ฅผ ๋ฐ๊พผ๋ค.
- ํ์ ํฌ๊ธฐ๊ฐ 1 ์ค์ด๋ ๊ฒ์ผ๋ก ๊ฐ์ฃผํ๋ค. (๋ง์ง๋ง ๊ฐ์ ํ์ ์ผ๋ถ๊ฐ ์๋ ๊ฒ์ผ๋ก ๊ฐ์ฃผํ๋ค. )
- ๋ฃจํธ๋ ธ๋์ ๋ํด์ Heapify(1)์ ํ๋ค. (remove node ํ์ ๋์ ๊ณผ์ ์ ๋ฐ๋ณตํ๋ค)
- 2๋ฒ ~ 4๋ฒ ๊ณผ์ ์ ๋ฐ๋ณตํ๋ค.
- ์ต์
์ ๊ฒฝ์ฐ ์๊ฐ ๋ณต์ก๋
$$O(NlogN)$$ - sorts in place - ์ถ๊ฐ ๋ฐฐ์ด์ด ํ์ํ์ง ์๋ค.
- ์ด์ง ํ ์๋ฃ๊ตฌ์กฐ(binary heap)๋ฅผ ์ฌ์ฉํ๋ค.
- Heap ์๋ฃ๊ตฌ์กฐ
- complete binary tree์ด๋ฉด์ ( -> ์ธ๋ฑ์ค๋ก ๋ถ๋ชจ, ์์ ๊ด๊ณ๋ฅผ ํํํ ์ ์๊ฒ ๋๋ค.)
- Heap property๋ฅผ ๋ง์กฑํด์ผํ๋ค. (๋ถ๋ชจ์ ์์ ๊ฐ ๊ด๊ณ)
- maxHeap : ๋ถ๋ชจ๋ ์์๋ณด๋ค ํฌ๊ฑฐ๋ ๊ฐ๋ค.
- minHeap : ๋ถ๋ชจ๋ ์์๋ณด๋ค ์๊ฑฐ๋ ๊ฐ๋ค.
- ํ์ ๋์ผํ ๋ฐ์ดํฐ๋ผ๋, ์ฝ์ ์์์ ๋ฐ๋ผ ๋ค์ํ ํํ๋ฅผ ๊ฐ์ง ์ ์๋ค.
- Heap ์๋ฃ๊ตฌ์กฐ
HEAPSORT(A) // O(NlogN)
BUILD-MAX-HEAP(A) // O(n)
for i <- heapSize downto 2 do // n-1 times
exchange A[1] <-> A[i] // O(1)
heapSize <- heapSize - 1 // O(1)
MAX-HEAPFIY(A, 1) // O(logN)
func heapSort(_ array: [Int], _ reverse: Bool = false) -> [Int] {
var array = array
var result = [Int]()
for i in stride(from: array.count - 1 , to: -1, by: -1) {
if i == 0 { // ์์๊ฐ ํ๋๋ง ์์ ๋๋ ๋จ์ํ ์ถ๊ฐํด์ฃผ๋ฉด ๋๋ค.
result.append(array.removeLast())
} else { // ๋จ์ ์์๊ฐ ์ฌ๋ฌ๊ฐ๋ผ๋ฉด, ๋จ์ ๋ฆฌ์คํธ๋ฅผ ๊ธฐ์ค์ผ๋ก ํ์ ๋ง๋ ๋ค.
array = buildMaxHeap(array)
array.swapAt(i, 0) // ๋ฆฌํ๋
ธ๋๋ฅผ ๋งจ ์์ผ๋ก ๊ฐ์ ธ์จ๋ค.
result.append(array.removeLast()) // ๋ฃจํธ ๋
ธ๋๋ฅผ ์ ๊ฑฐํ ํ ๊ฒฐ๊ณผ ๋ฆฌ์คํธ์ ์ถ๊ฐํ๋ค.
}
}
if !reverse { // ์ ๋ ฌ ๊ธฐ์ค ์ ํ
result.reverse()
}
return result
}
func buildMaxHeap(_ array: inout [Int]) {
for i in 0 ..< array.count { // 1๋ฒ๋ถํฐ ๋ง์ง๋ง ๋
ธ๋๊น์ง ์กฐํ
var child = i
while child != 0 { // i๋ฒ์งธ ๋
ธ๋์ ์์น๋ฅผ ์ง์ ํ๋ค.
let parent = child / 2
if array[parent] > array[child] { break }
array.swapAt(parent, child)
child = parent
}
}
}
[1] ๊ถ์คํ ๊ต์๋์ ๊ธฐ๋ณธ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ ๊ฐ์
[2] ๊ถ์คํ ๊ต์๋์ ํฉ๋ณ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ ๊ฐ์
[3] ๊ถ์คํ ๊ต์๋์ ๋น ๋ฅธ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ ๊ฐ์