์ค์ํํธ๋ก ๊ตฌํํ๋ ์๋ฃ๊ตฌ์กฐ 5: ํ(Heap)
ํ (Heap)
ํ์ ์ด์งํธ๋ฆฌ๋ฅผ ์ฌ์ฉํด์ ๋ฐ์ดํฐ๋ค์ ๋ฐ์ ๋ ฌ ์ํ๋ก ์ ์งํ๋ ์๋ฃ๊ตฌ์กฐ์ ๋๋ค. ํ์ ํธ๋ฆฌ์ ๋ฃจํธ ๋ ธ๋์ ๋ฐ์ดํฐ๋ค์ ์ต์๊ฐ ํน์ ์ต๋๊ฐ์ ์ ์ฅํ๋๋ฐ์, ์ต์๊ฐ์ ๋ฃจํธ์ ๋ ๋๋ ์ต์ํ, ์ต๋๊ฐ์ ๋ฃจํธ์ ๋๋ฉด ์ต๋ํ์ด๋ผ๊ณ ํฉ๋๋ค.
์์ ์ด์ง ํธ๋ฆฌ
์ด์ง ํธ๋ฆฌ๋ ํธ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ๋ ๋ชจ๋ ๋ ธ๋๊ฐ ์ต๋ ๋ ๊ฐ์ ์์ ๋ ธ๋๋ฅผ ๊ฐ์ง๋ ์๋ฃ๊ตฌ์กฐ์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์์ ์ด์ง ํธ๋ฆฌ๋ ๊ฐ ๋์ด์ ์๋ ๋ชจ๋ ๋ ธ๋๊ฐ ์์ ๋ ธ๋๋ฅผ ๊ฐ์ ธ์ผ ๋ค์ ๋์ด์ ์ ๋ ธ๋๋ฅผ ์ถ๊ฐํ ์ ์๊ณ , ๊ฐ์ฅ ์ผ์ชฝ๋ถํฐ ์ฐจ๋ก๋๋ก ๋ ธ๋๋ฅผ ์ฑ์์ผํฉ๋๋ค.
์ด๋ฐ ์ด์ง ํธ๋ฆฌ๋ ๋ฐฐ์ด๋ก๋ ๊ตฌํ์ด ๊ฐ๋ฅํ๋ฐ์, ๋ฃจํธ ๋ ธ๋๋ฅผ ์ธ๋ฑ์ค 1๋ก ์ผ์ผ๋ฉด ์ด๋ค index ๋ฒ์งธ ๋ ธ๋์ ์ผ์ชฝ ์์ ๋ ธ๋๋ index * 2, ์ค๋ฅธ์ชฝ ์์ ๋ ธ๋๋ (index * 2) + 1 ๋ก ๊ตฌํ ์ ์์ต๋๋ค.
์ฐ๋ฆฌ๋ ํ์ ์ด ๋ฐฐ์ด ๊ธฐ๋ฐ์ ์ด์ง ํธ๋ฆฌ๋ฅผ ํตํด์ ๊ตฌํํ ๊ฑฐ์์!
๊ทธ๋ฆฌ๊ณ ํ์ ์ด์ง ํธ๋ฆฌ๋ ํธ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ๋ ๊ฐ ์๋ธ ํธ๋ฆฌ๋ค๋ ๋ชจ๋ ํ์ ๋ง์กฑํด์ผํฉ๋๋ค.
๋ผ๋ ๋ง๋ค๊ธฐ
import Foundation
struct Heap<T: Comparable> {
private var elements: [T] = []
private let sortFunction: (T, T) -> Bool
var isEmpty: Bool {
return self.elements.count == 1
}
var peek: T? {
if self.isEmpty { return nil }
return self.elements[1]
}
var count: Int {
return self.elements.count - 1
}
init(elements: [T] = [], sortFunction: @escaping (T, T) -> Bool) {
if !elements.isEmpty {
self.elements = [elements.first!] + elements
} else {
self.elements = elements
}
self.sortFunction = sortFunction
if elements.count > 1 {
self.buildHeap()
}
}
func leftChild(of index: Int) -> Int {
return index * 2
}
func rightChild(of index: Int) -> Int {
return index * 2 + 1
}
func parent(of index: Int) -> Int {
return (index) / 2
}
}
๋จผ์ ๊ธฐ๋ณธ์ ์ธ ํ๋กํผํฐ๋ค๊ณผ ์์ฑ์, ๋ฉ์๋๋ฅผ ๊ตฌํํด์ฃผ์์ต๋๋ค.
elements ๋ ์ค์ ๋ก ๋ฐ์ดํฐ๋ค์ ์ ์ฅํ ์ด์งํธ๋ฆฌ๋ก ํํ๋ ๋ฐฐ์ด์ด๊ณ , sortFunction์ ์ต์ํ, ์ต๋ํ์ ๊ธฐ์ค์ ์ผ๋ก ์ผ์ ์ ๋ ฌ ๋ก์ง์ ๊ฐ์ง ํด๋ก์ ์ ๋๋ค. ๋ง์ฝ ์ ์ฅ๋๋ ๋ฐ์ดํฐ๊ฐ ์ ์์ด๊ณ , sortFunction์ด ์ค๋ฆ์ฐจ์ ์ ๋ ฌ์ด๋ฉด ์ต์ํ์ด ๋๊ณ , ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ์ด๋ฉด ์ต๋ํ์ด ๋๊ฒ ์ฃ ?
isEmpty ํ๋กํผํฐ๋ ํ์ฌ ์ด์งํธ๋ฆฌ์ ์์๋ค์ด 1๊ฐ์ธ์ง ํ์ธํ๋ ๊ฒ์ผ๋ก ํ๋ณํฉ๋๋ค. ๋ฐฐ์ด์ 0๋ฒ์งธ ์ธ๋ฑ์ค๋ ์ฌ์ฉํ์ง ์๋ ๊ฐ์ด๋ ๋ฐฐ์ด์ ๊ฐ์ด ํ๋๋ง ์์ ๋ ํธ๋ฆฌ๊ฐ ๋น์์ ธ ์๋ ๊ฒ์ ๋๋ค.
leftChild, rightChild, parent๋ ์์์ ์ค๋ช ํ๋๋๋ก ๋ถ๋ชจ์ ์์๋ ธ๋์ ์ธ๋ฑ์ค๋ฅผ ๊ตฌํ๋ ๋ฉ์๋์ด๊ตฌ์, ์์ฑ์์ buildHeap๋ ์ ์ ๋ค์ ์ค๋ช ํ๊ฒ ์ต๋๋ค!
์ฝ์ (insert) - O(log N)
ํ์ ์ฝ์ ์ ๋ค์๊ณผ ๊ฐ์ ๊ณผ์ ์ผ๋ก ์งํ๋ฉ๋๋ค.
์ด๋ ๊ฒ ์ต๋ํ์ด ์์ ๋ ์๋ก์ด ๋ฃจํธ๋ ธ๋๊ฐ ๋ ๋ ธ๋๋ฅผ ํ๋ ์ฝ์ ํ๋ค๊ณ ํด๋ณด๊ฒ ์ต๋๋ค.
๋จผ์ ๊ฐ์ฅ ์ผ์ชฝ ๋ฆฌํ๋ ธ๋์ ์๋ก ์ถ๊ฐํ ๋ ธ๋๋ฅผ ๋ถ์ฌ์ค๋๋ค.
์ด์ ์ต๋ ํ์ ์ ์งํ๊ธฐ ์ํด ํธ๋ฆฌ๋ฅผ ์ฌ์กฐ์ ํด์ฃผ์ด์ผ ํ๋๋ฐ์, ๊ฐ์ฅ ๋์ ๋ ธ๋๋ฅผ ๋ถ์์ผ๋ ์ด ๋ ธ๋๋ฅผ ์ฌ๋ผ๊ฐ ์ ์๋ ์ต๋ํ ์ฌ๋ ค์ฃผ์ด์ผ ํฉ๋๋ค. ๊ทธ๋์ผ ํธ๋ฆฌ์ ๊ฐ ์๋ธ ํธ๋ฆฌ๋ค๋ ์ต๋ ํ์ ๋ง์กฑํ๋๊น์.
๋จผ์ 9๋ ๋ถ๋ชจ ๋ ธ๋์ธ 1๋ณด๋ค ํฌ๊ธฐ ๋๋ฌธ์ ๋ ๋ ธ๋๋ฅผ ๊ตํํด์ค๋๋ค.
9์ ์๋ก์ด ๋ถ๋ชจ ๋ ธ๋ 4๋ 9๋ณด๋ค ์๋ค์. ๋ค์ ๊ตํํฉ์๋ค.
๊ทธ๋ฆฌ๊ณ ๋ค์ ์๋ก์ด ๋ถ๋ชจ๋ ธ๋์ธ 7๋ณด๋ค๋ ํฌ๊ธฐ ๋๋ฌธ์ ์๋ก์ด ๋ฃจํธ๋ ธ๋๋ 9๊ฐ ๋ฉ๋๋ค.
์ ์ฒด ํธ๋ฆฌ์ ๋ชจ๋ ์๋ธํธ๋ฆฌ๊ฐ ์ต๋ํ์ ๋ง์กฑํ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค!
์ฝ์ ๊ตฌํ - swimUp
๊ฒฐ๊ตญ ์ฝ์ ์ฐ์ฐ์
1) ํธ๋ฆฌ ์ ์ผ ๋์ ์ ๋ ธ๋ ๋ถ์ด๊ธฐ
2) ์ ๋ ธ๋๋ฅผ ์ฌ๋ฆด ์ ์๋๋ฐ๊น์ง ์ฌ๋ฆฌ๊ธฐ
๋ ๋จ๊ณ๋ก ์งํ๋ฉ๋๋ค.
์ด๋ 2๋ฒ ๊ณผ์ ์ ์ ์๊ฒ ์๋ฃ๊ตฌ์กฐ๋ฅผ ๊ฐ๋ฅด์ณ์ฃผ์ ๊ต์๋์ swimUp ์ด๋ผ๊ณ ํํํ์ จ๋๋ฐ์, ๋ง์น ์์ํด์ ์ฌ๋ผ๊ฐ๋ ๊ฒ ๊ฐ๋ค๊ณ ...
swimUp์ ๊ตฌํํด๋ด ์๋ค.
mutating func swimUp(from index: Int) {
var index = index
while index != 1 && self.sortFunction(self.elements[index], self.elements[self.parent(of: index)]) {
self.elements.swapAt(index, self.parent(of: index))
index = self.parent(of: index)
}
}
๋๋ฌ์ต๋๋ค..ใ ใ ใ ใ
๋ฃจํธ๋ ธ๋์ ๋ค๋ค๋ฅด๊ฑฐ๋, ํ์ฌ ๋ ธ๋๊ฐ ๋ถ๋ชจ ๋ ธ๋๋ณด๋ค ์ฐ์ ์์๊ฐ ๋ฎ์์ง๊ธฐ ์ ๊น์ง ๋ ธ๋์ ๋ถ๋ชจ๋ ธ๋๋ฅผ ๊ณ์ ๊ตํํด์ค๋๋ค. ์ ๊ทธ๋ฆผ์ ์์์ ๋ํ ์๊ณ ๋ฆฌ์ฆ ๋์ ๊ณผ์ ์ ์จ๋ณด๋ฉด
1. ํ์ฌ ์ธ๋ฑ์ค 8๋ถํฐ swimUp ์์!
2. ํ์ฌ ์ธ๋ฑ์ค์ ๊ฐ 9๋ ๋ถ๋ชจ ์ธ๋ฑ์ค 4์ ๊ฐ 1๋ณด๋ค ํฌ๊ธฐ ๋๋ฌธ์ ๋ ๋ ธ๋์ ๊ฐ์ ๊ตํํ๊ณ ํ์ฌ ์ธ๋ฑ์ค๋ฅผ ๋ถ๋ชจ ์ธ๋ฑ์ค์ธ 4๋ก ๋ณ๊ฒฝํฉ๋๋ค.
3. ํ์ฌ ์ธ๋ฑ์ค 4์ ๊ฐ 9๋ ๋ถ๋ชจ ์ธ๋ฑ์ค 2์ ๊ฐ 4๋ณด๋ค ํฌ๊ธฐ ๋๋ฌธ์ ๋ ๋ ธ๋์ ๊ฐ์ ๊ตํํ๊ณ ํ์ฌ ์ธ๋ฑ์ค๋ฅผ ๋ถ๋ชจ ์ธ๋ฑ์ค์ธ 2๋ก ๋ณ๊ฒฝํฉ๋๋ค.
4. ํ์ฌ ์ธ๋ฑ์ค 2์ ๊ฐ 9๋ ๋ถ๋ชจ ์ธ๋ฑ์ค 1์ ๊ฐ 7๋ณด๋ค ํฌ๊ธฐ ๋๋ฌธ์ ๋ ๋ ธ๋์ ๊ฐ์ ๊ตํํ๊ณ ํ์ฌ ์ธ๋ฑ์ค๋ฅผ ๋ถ๋ชจ ์ธ๋ฑ์ค์ธ 1๋ก ๋ณ๊ฒฝํฉ๋๋ค.
5. ํ์ฌ ์ธ๋ฑ์ค๋ 1์ด๊ธฐ ๋๋ฌธ์ while๋ฌธ์ ๋น ์ ธ๋์์ ํจ์๋ ์ข ๋ฃ๋ฉ๋๋ค.
์ด ์๊ณ ๋ฆฌ์ฆ์ ์ต์ ์ ๊ฒฝ์ฐ์๋ ์ง๊ธ์ฒ๋ผ ๋ฆฌํ๋ ธ๋๋ถํฐ ๋ฃจํธ๋ ธ๋๊น์ง ๊ฑฐ์ฌ๋ฌ ์ฌ๋ผ๊ฐ๋ฉฐ ๊ตํ์ ์งํํ๊ธฐ ๋๋ฌธ์ ์๊ฐ๋ณต์ก๋๋ ํธ๋ฆฌ์ ๋์ด์ ๋ํ ๋ ธ๋ ๊ฐ์์ธ O(log N)๊ฐ ๋ฉ๋๋ค.
๋ฐ๋ผ์ ์ ์ฒด ์ฝ์ ๊ณผ์ ์ ํธ๋ฆฌ ๋์ ๋ฐ์ดํฐ๋ฅผ ํ๋ ์ฝ์ ํ๊ณ swimUp์ ์ํํ๋ O(1) + O(log N) = O(log N)๊ฐ ๋ฉ๋๋ค.
mutating func insert(node: T) {
if self.elements.isEmpty {
self.elements.append(node)
return
}
self.elements.append(node)
self.swimUp(from: self.elements.endIndex - 1)
}
์ญ์ (delete) - O(log N)
์ญ์ ๋ ๋ฃจํธ๋ ธ๋์ ์๋ ๊ฐ์ฅ ์ฐ์ ์์๊ฐ ๋์ ๋ ธ๋๋ฅผ ๊บผ๋ด๊ณ ํธ๋ฆฌ๋ฅผ ์ฌ์กฐ์ ํ๋ ์์ ์ด ํ์ํฉ๋๋ค.
์ฌ๊ธฐ์ ์ญ์ ๋ฅผ ํ๋ฉด ๋ฃจํธ๋ ธ๋๊ฐ ๋์ค๊ฒ ์ฃ ? ํ์์์ ์ญ์ ๋ ๋ฃจํธ๋ ธ๋์ ๋ง์ง๋ง ๋ฆฌํ ๋ ธ๋๋ฅผ ๊ตํํด์ฃผ๋ ๊ฒ์ผ๋ก ์์๋ฉ๋๋ค.
์ด๋ ๊ฒ ๊ตํ๋๋ฉด ๋ฃจํธ๋ ธ๋ ์๋ ๋ ธ๋๋ฅผ ์ ๊ฑฐํด์ฃผ๋ ๊ฒ์ ๊ฐ๋จํ๊ฒ ์ฃ ? ํธ๋ฆฌ์์ ์ฐ๊ฒฐ์ ๋์ด์ค๋๋ค.
์ฐ๋ฆฌ๋ ์ด์ง ํธ๋ฆฌ๊ฐ ๋ฐฐ์ด๋ก ๊ตฌํ๋์ด ์๊ธฐ ๋๋ฌธ์ ๋ ธ๋์ ์ญ์ ๊ฐ ์ด๋ ต์ง ์์ต๋๋ค. ๊ทธ๋ฅ ๋ฐฐ์ด์์ ๋ง์ง๋ง ๊ฐ์ ๋นผ์ฃผ๋ฉด ๋๋๊น์!
๋์ ์ต๋ํ์ด ๊นจ์ก๊ธฐ ๋๋ฌธ์ ๋ค์ ํธ๋ฆฌ๋ฅผ ์ฌ์กฐ์ ํด์ผ ํฉ๋๋ค.
๋ฃจํธ ๋ ธ๋์ ์์ ๋ ธ๋๋ค ์ค์ ์ฐ์ ์์๊ฐ ๋ ๋์ ๋ ธ๋๋ฅผ ๊ณจ๋ผ ํ์ฌ ๋ฃจํธ ๋ ธ๋์ ๋ณ๊ฒฝํด์ค์๋ค.
์ด์ ์๋ ๋ฃจํธ๋ ธ๋์ ์๋ ๋ ธ๋๊ฐ ์ด๋ํ๋ฉด์ ์๋ธํธ๋ฆฌ์ ์๋ก์ด ๋ฃจํธ ๋ ธ๋๊ฐ ๋ฉ๋๋ค. ๋ฐ๋ผ์ ์๋ธํธ๋ฆฌ๊ฐ ์ต๋ ํ์ ๋ง์กฑํ๋์ง ํ์ธํด๋ด์ผ๊ฒ ์ฃ ? ์ด๋ฒ์๋ ์์ ๋ ธ๋๋ค ์ค์ ์ฐ์ ์์๊ฐ ๊ฐ์ฅ ๋์ ๋ ธ๋์ ์๋ธํธ๋ฆฌ์ ๋ฃจํธ๋ ธ๋๋ฅผ ๋น๊ตํด๋ด ๋๋ค.
๋ฃจํธ๋ ธ๋๋ 5์ด๊ณ , ์์๋ ธ๋๋ ํ๋ ๋ฟ์ธ 2์ด๊ธฐ ๋๋ฌธ์ ํ์ฌ ํธ๋ฆฌ์ ์ํ๊ฐ ์ ์ง๋ฉ๋๋ค.
์ด๋ ๊ฒ ํ๋ฉด ๋ชจ๋ ์๋ธ ํธ๋ฆฌ์ ์ต๋ ํ์ ์ ์งํ๋ฉด์ ๋ฃจํธ๋ ธ๋๋ฅผ ์ ๊ฑฐํ ์ ์๊ฒ๋ฉ๋๋ค.
์ญ์ ๊ตฌํ - diveDown
์์ ์ค๋ช ํ๋๋ก ์ญ์ ์ฐ์ฐ์ ๋ฃจํธ ๋ ธ๋์ ๋ฆฌํ ๋ ธ๋์ ๊ตํ, ๊ทธ๋ฆฌ๊ณ ํธ๋ฆฌ์ ์ฌ์กฐ์ ์ ์์๋ก ์งํ๋ฉ๋๋ค.
swimUp์ ๋ช ๋ช ํ์ ๊ต์๋๊ป์๋ ๋ฃจํธ๋ ธ๋์์๋ถํฐ ํ์ ๋ ธ๋๋ค์ ๊ฐฑ์ ํ๋ฉด์ ์ ์ง์ ์ผ๋ก ๋ด๋ ค๊ฐ๋ ํจ์๋ฅผ diveDown์ผ๋ก ๋ช ๋ช ํ์ จ๋๋ฐ์. ์ด๊ฒ๋ ์์์๋ถํฐ ๋ค์ด๋นํด์ ๋ด๋ ค์ค๋ ๊ฒ ๊ฐ๋ค๊ณ ...
mutating func diveDown(from index: Int) {
var higherPriority = index
let leftIndex = self.leftChild(of: index)
let rightIndex = self.rightChild(of: index)
// ์ผ์ชฝ ์์ ๋
ธ๋๊ฐ ๋ ์ฐ์ ์์๊ฐ ๋์ ๋
if leftIndex < self.elements.endIndex && self.sortFunction(self.elements[leftIndex], self.elements[higherPriority]) {
higherPriority = leftIndex
}
// ์ค๋ฅธ์ชฝ ์์ ๋
ธ๋๊ฐ ๋ ์ฐ์ ์์๊ฐ ๋์ ๋
if rightIndex < self.elements.endIndex && self.sortFunction(self.elements[rightIndex], self.elements[higherPriority]) {
higherPriority = rightIndex
}
// ๊ตํ์ด ํ์ํ ๊ฒฝ์ฐ๋ ๊ตํ ํ ์๋ธํธ๋ฆฌ๋ก ์ด๋
if higherPriority != index {
self.elements.swapAt(higherPriority, index)
self.diveDown(from: higherPriority)
}
}
diveDown์ ๊ตฌํ์ ์ด๋ ๊ฒ ๋ฉ๋๋ค.
๋ ์ด์ ๊ตํ์ด ํ์์์ ๋๊น์ง ์ผ์ชฝ ์์๋ ธ๋์ ์ค๋ฅธ์ชฝ ์์ ๋ ธ๋๋ฅผ ํ์ฌ ๋ฃจํธ ๋ ธ๋์ ๋น๊ตํ๋ฉด์ ์ฐ์ ์์๊ฐ ๋ ๋์ ๋ ธ๋์ ๊ตํ์ ์งํํด์ฃผ๊ณ , ๊ตํ์ด ๋๋ฉด ์๋ก์ด ๋ ธ๋๋ฅผ ๋ฃจํธ ๋ ธ๋๋ก ์ผ์์ diveDown์ ์ฌ๊ท์ ์ผ๋ก ์งํํฉ๋๋ค.
์ด๋ฒ์๋ ๋ฃจํธ์ ๋ฆฌํ๋ฅผ ๊ตํํ๋ ์๊ฐ๋ณต์ก๋ O(1), ์ต์ ์ ๊ฒฝ์ฐ ๋ฃจํธ๋ ธ๋๋ถํฐ ๋ฆฌํ๋ ธ๋๊น์ง ๊ตํ์ ์งํํ๋ ์๊ฐ๋ณต์ก๋ O(log N)๋ก ์ญ์ ์ฐ์ฐ์ O(log N)์ ์๊ฐ๋ณต์ก๋๊ฐ ์๊ตฌ๋ฉ๋๋ค.
๋ฐฐ์ด์ ํ์ผ๋ก - Build Heap
init(elements: [T] = [], sortFunction: @escaping (T, T) -> Bool) {
if !elements.isEmpty {
self.elements = [elements.first!] + elements
} else {
self.elements = elements
}
self.sortFunction = sortFunction
if elements.count > 1 {
self.buildHeap()
}
}
์๊น ์์ฑ์๋ฅผ ์ด๋ ๊ฒ ๊ตฌํํ์๋๋ฐ์, ๋ง์ฝ ์์ฑ์๋ก ๋ฐ์ ๋ฐฐ์ด์ ๊ฐ์ด ๋ค์ด ์๋ค๋ฉด ๋ฐฐ์ด ์ ์ฒด๋ฅผ ํ์ผ๋ก ๋ค์ ์ฌ๊ตฌ์ฑ ํด์ฃผ์ด์ผํ๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ์ํด์ buildHeap์ด๋ผ๋ ๋ฉ์๋๋ฅผ ํธ์ถํ๊ณ ์์ต๋๋ค.
mutating func buildHeap() {
for index in (1...(self.elements.count / 2)).reversed() {
self.diveDown(from: index)
}
}
buildHeap์ ์ด๋ ๊ฒ ๊ตฌํ๋์ด ์์ต๋๋ค. ๋ฐฐ์ด์ ๋ค์ด์๋ ์์์ ๊ฐ์๋ฅผ 2๋ก ๋๋๋ฉด ๋ง์ง๋ง ๋ฆฌํ๋ ธ๋์ ๋ถ๋ชจ ๋ ธ๋๊ฐ ๋์ค๊ธฐ ๋๋ฌธ์ ์ด ๋ ธ๋๊ฐ ๋ฆฌํ๋ ธ๋๋ฅผ ์ ์ธํ๊ณ ๋ ๊ฐ์ฅ ๋ง์ง๋ง ๋ ธ๋๊ฐ ๋ฉ๋๋ค.
์ด ๋ ธ๋๋ถํฐ ๋ฃจํธ๋ ธ๋๊น์ง ์ญ์์ผ๋ก ๊ฐ ์๋ธํธ๋ฆฌ์ ๋ฃจํธ๋ ธ๋๋ค์ ์ํํ๋ฉด์ diveDown์ ํธ์ถํ๋ฉด ๊ฐ์ฅ ๋ง์ง๋ง ์๋ธํธ๋ฆฌ๋ถํฐ ์์๋๋ก ํ์ ์ฌ๊ตฌ์ฑํ๊ฒ ๋ฉ๋๋ค.
์ ์ฒด ์ฝ๋
์๋ฃ๊ตฌ์กฐ ์๋ฆฌ์ฆ์ ์ฝ๋๋ค์ ์ด ๋ ํฌ์์ ๋ชจ๋ ํ์ธํ ์ ์์ด์!
'๐ฎ ์จ-์์ค > ๐ฆด ์๋ฃ๊ตฌ์กฐ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote