์ด๊ธ์ ๊ฐ์ธ์ ์ธ ๊ณต๋ถ๋ฅผ ์ํด ์์ฑ๋ ๊ธ์์ ๋ฐํ๋๋ค.
์ด๊ธ์ ๋ชจ๋ ๋ด์ฉ์ ๋ํ ์ถ์ฒ๋ https://jeonyeohun.tistory.com/325 ์ด๊ณณ์ ๋๋ค.
ํ
์ด์งํธ๋ฆฌ๋ฅผ ์ฌ์ฉํด์ ๋ฐ์ ๋ ฌ ์ํ๋ก ์ ์งํ๋ ์๋ฃ๊ตฌ์กฐ
ํ์ ํธ๋ฆฌ์ ๋ฃจํธ ๋ ธ๋์ ๋ฐ์ดํฐ๋ค์ ์ต์๊ฐ ํน์ ์ต๋๊ฐ์ ์ ์ฅํฉ๋๋ค.
์ต์๊ฐ์ ๋ฃจํธ์ ๋ ๋๋ ์ต์ํ, ์ต๋๊ฐ์ ๋ฃจํธ์ ๋๋ฉด ์ต๋ํ์ด๋ผ๊ณ ํฉ๋๋ค.
์์ ์ด์งํธ๋ฆฌ
ํธ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ๋ ๋ชจ๋ ๋ ธ๋๊ฐ ์ต๋ 2๊ฐ์ ์์๋ ธ๋๋ฅผ ๊ฐ์ง๋ ์๋ฃ๊ตฌ์กฐ
์์ ์ด์งํธ๋ฆฌ๋ ์๋์ ๊ฐ์ ํน์ง์ ๊ฐ์ง๋๋ค.
1. ๊ฐ ๋์ด์ ์๋ ๋ชจ๋ ๋ ธ๋๊ฐ ์์๋ ธ๋๋ฅผ ๊ฐ์ ธ์ผ ๋ค์ ๋์ด์ ์ ๋ ธ๋๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค.
2. ๊ฐ์ฅ ์ผ์ชฝ๋ถํฐ ์ฐจ๋ก๋๋ก ๋ ธ๋๋ฅผ ์ฑ์์ผ ํฉ๋๋ค.
์ด ๋ฐฐ์ด ๊ธฐ๋ฐ์ ์ด์งํธ๋ฆฌ๋ฅผ ์ด์ฉํด์ ํ์ ๊ตฌํํ๊ฒ ์ต๋๋ค.
ํ์ ์ด์งํธ๋ฆฌ๋ ํธ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ๋ ๊ฐ ์๋ธํธ๋ฆฌ๋ค๋ ๋ชจ๋ ํ์ ๋ง์กฑํด์ผํฉ๋๋ค.
๋ผ๋ ๋ง๋ค๊ธฐ
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๊ฐ์ธ์ง ํ์ธํฉ๋๋ค.
leftChild, rightChild, parent
๋ถ๋ชจ์ ์์๋ ธ๋์ ์ธ๋ฑ์ค๋ฅผ ๊ตฌํ๋ ๋ฉ์๋
์ฝ์ - O(logN)
์ด๋ ๊ฒ ์ต๋ํ์ด ์๊ณ , 9๋ฅผ ์ฝ์ ํด๋ณด๊ฒ ์ต๋๋ค.
์ด๋ฌํ ๊ณผ์ ๋ค์ ๊ฑฐ์ณ ํธ๋ฆฌ๊ฐ ์ฌ์กฐ์ ๋ ๊ฒ์ ๋๋ค.
๊ฐ์ฅ ๋์ ๋ ธ๋๋ฅผ ๋ถ์์ผ๋ ๋ ธ๋๋ฅผ ์ฌ๋ผ๊ฐ ์ ์๋ ๋งํผ ์ต๋ํ ์ฌ๋ ค์ฃผ์ด์ผํฉ๋๋ค.
๊ทธ๋์ผ ํธ๋ฆฌ์ ๊ฐ ์๋ธํธ๋ฆฌ๋ค๋ ์ต๋ํ์ ๋ง์กฑํ๊ฒ๋ฉ๋๋ค.
์ ์ฒดํธ๋ฆฌ์ ๋ชจ๋ ์๋ธํธ๋ฆฌ๊ฐ ์ต๋ํ์ ๋ง์กฑํ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
์ฝ์ ๊ตฌํ - swimUp
์ฝ์ ์ ์ฐ์ฐ์
1. ํธ๋ฆฌ ์ ์ผ ๋์ ์ ๋ ธ๋ ๋ถ์ด๊ธฐ
2. ์ ๋ ธ๋๋ฅผ ์ฌ๋ฆด ์ ์๋ ๊ณณ๊น์ง ์ฌ๋ฆฌ๊ธฐ
์ด ์์๋ก ์งํ๋ฉ๋๋ค.
2๋ฒ ๊ณผ์ ์ ์๋์ ๊ฐ์ด ๊ตฌํ์ด ๊ฐ๋ฅํฉ๋๋ค.
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)
}
}
๋ฃจํธ๋ ธ๋์ ๋ค๋ค๋ฅด๊ฑฐ๋, ํ์ฌ๋ ธ๋๊ฐ ๋ถ๋ชจ๋ ธ๋๋ณด๋ค ์ฐ์ ์์๊ฐ ๋ฎ์์ง๊ธฐ ์ ๊น์ง ๋ ธ๋์ ๋ถ๋ชจ๋ ธ๋๋ฅผ ๊ณ์ ๊ตํํด์ค๋๋ค.
์ด ์๊ณ ๋ฆฌ์ฆ์ ์ต์ ์ ๊ฒฝ์ฐ์๋ ์ง๊ธ ๋ฆฌํ๋ ธ๋๋ถํฐ ๋ฃจํธ๋ ธ๋๊น์ง ๊ฑฐ์ฌ๋ฌ ์ฌ๋ผ๊ฐ๋ฉฐ ๊ตํ์ ์งํํ๊ธฐ ๋๋ฌธ์
์๊ฐ๋ณต์ก๋๋ ํธ๋ฆฌ์ ๋์ด์ ๋ํ ๋ ธ๋๊ฐ์์ธ O(logN)์ด ๋ฉ๋๋ค.
1๋ฒ ๊ณผ์ ๊ณผ 2๋ฒ๊ณผ์ ์ ํฉํ ์ ์ฒด ์ฝ์ ์ ๊ตฌํ์ ์๋์ ๊ฐ์ต๋๋ค.
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)
}
์ญ์ - O(logN)
์ญ์ ๋ฅผ ์ํด ๋ฃจํธ๋ ธ๋์ ๋ง์ง๋ง ๋ฆฌํ๋ ธ๋๋ฅผ ๊ตํํด์ค๋๋ค.
์ต๋ํ์ด ๊นจ์ก๊ธฐ ๋๋ฌธ์ ํธ๋ฆฌ๋ฅผ ์ฌ์กฐ์ ํฉ๋๋ค.
๋ฃจํธ๋ ธ๋์ ์์๋ ธ๋๋ค ์ค์ ์ฐ์ ์์๊ฐ ๋ ๋์ ๋ ธ๋๋ฅผ ๊ณจ๋ผ ํ์ฌ ๋ฃจํธ๋ ธ๋์ ๋ณ๊ฒฝํด์ค๋๋ค.
์ด๋ ๊ฒ ํ๋ฉด ๋ชจ๋ ์๋ธํธ๋ฆฌ์ ์ต๋ํ์ ์ ์งํ๋ฉด์ ๋ฃจํธ๋ ธ๋๋ฅผ ์ ๊ฑฐํ ์ ์๊ฒ๋ฉ๋๋ค.
์ญ์ ๊ตฌํ - diveDown
์ญ์ ์ ์ฐ์ฐ์
1. ๋ฃจํธ๋ ธ๋์ ๋ฆฌํ๋ ธ๋๋ฅผ ๊ตํํฉ๋๋ค.
2. ํธ๋ฆฌ๋ฅผ ์ฌ์กฐ์ ํฉ๋๋ค.
์ ๋๊ฐ์ง ์์๋ก ์งํ๋ฉ๋๋ค.
2๋ฒ๊ณผ์ ์ ์๋์ ๊ฐ์ด ๊ตฌํํฉ๋๋ค.
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์ ์ฌ๊ท์ ์ผ๋ก ์งํํฉ๋๋ค.
์ต์ ์ ๊ฒฝ์ฐ ๋ฃจํธ๋ ธ๋๋ถํฐ ๋ฆฌํ๋ ธ๋๊น์ง ๊ตํ์ ์งํํ๋ ์๊ฐ๋ณต์ก๋ O(logN)๊ฐ ์๊ตฌ๋ฉ๋๋ค.
1๋ฒ ๊ณผ์ ๊ณผ 2๋ฒ๊ณผ์ ์ ํฉ์ณ ์ญ์ ๋ฅผ ์๋์ ๊ฐ์ด ๊ตฌํํ ์ ์์ต๋๋ค.
mutating func remove() -> T? {
if self.isEmpty { return nil }
self.elements.swapAt(1, elements.endIndex - 1)
let deleted = elements.removeLast()
self.diveDown(from: 1)
return deleted
}
๋ฐฐ์ด์ ํ์ผ๋ก - Build Heap
๋ง์ฝ ์์ฑ์๋ก ๋ฐ์ ๋ฐฐ์ด์ ๊ฐ์ด ๋ค์ด ์๋ค๋ฉด ๋ฐฐ์ด ์ ์ฒด๋ฅผ ๋ค์ ํ์ผ๋ก ์ฌ๊ตฌ์ฑํด์ฃผ์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ์์ฑ์์์ buildHeap์ด๋ผ๋ ๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค.
mutating func buildHeap() {
for index in (1...(self.elements.count / 2)).reversed() {
self.diveDown(from: index)
}
}
์ ์ฒด ์ฝ๋
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.last!
}
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
}
mutating func add(element: T) {
self.elements.append(element)
}
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)
}
}
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)
}
}
mutating func buildHeap() {
for index in (1...(self.elements.count / 2)).reversed() {
self.diveDown(from: index)
}
}
mutating func insert(node: T) {
if self.elements.isEmpty {
self.elements.append(node)
}
self.elements.append(node)
self.swimUp(from: self.elements.endIndex - 1)
}
mutating func remove() -> T? {
if self.isEmpty { return nil }
self.elements.swapAt(1, elements.endIndex - 1)
let deleted = elements.removeLast()
self.diveDown(from: 1)
return deleted
}
}
๊ฐ์ํ ์ฝ๋
struct Heap<T: Comparable> {
private var elements: [T] = []
private let comparer: (T, T) -> Bool
init(comparer: @escaping (T,T) -> Bool) {
self.comparer = comparer
}
mutating func insert(element: T) {
if elements.isEmpty {
elements.append(element)
elements.append(element)
return
}
elements.append(element)
swimUp(index: elements.count - 1)
}
mutating private func swimUp(index: Int) {
var index = index
while index > 1 && comparer(elements[index], elements[index / 2]) {
elements.swapAt(index, index / 2)
index /= 2
}
}
mutating func pop() -> T? {
if elements.count < 2 { return nil }
elements.swapAt(1, elements.count - 1)
let deletedElement = elements.removeLast()
diveDown(index: 1)
return deletedElement
}
mutating private func diveDown(index: Int) {
var swapIndex = index
var isSwap = false
let leftIndex = index * 2
let rightIndex = index * 2 + 1
if leftIndex < elements.endIndex && comparer(elements[leftIndex], elements[swapIndex]) {
swapIndex = leftIndex
isSwap = true
}
if rightIndex < elements.endIndex && comparer(elements[rightIndex], elements[swapIndex]) {
swapIndex = rightIndex
isSwap = true
}
if isSwap {
elements.swapAt(swapIndex, index)
diveDown(index: swapIndex)
}
}
}
var maxHeap = Heap<Int>(comparer: >)
var minHeap = Heap<Int>(comparer: <)
์ถ์ฒ : https://dev-mandos.tistory.com/246 (๋ง๋์ค๋ ํฐ์คํ ๋ฆฌ)
'๐ป CS > ์๋ฃ๊ตฌ์กฐ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Swift] ์ฐ์ ์์ ํ(Priority Queue) ๊ตฌํํด๋ณด๊ธฐ (0) | 2023.04.11 |
---|---|
[Swift] ๊ทธ๋ํ(Graph) (0) | 2023.03.29 |
[Swift] ๋ฑ ๊ตฌํํด๋ณด๊ธฐ (0) | 2023.03.29 |
[Swift] ์คํ ๊ตฌํํด๋ณด๊ธฐ (0) | 2023.03.29 |
[Swift] ํ(Queue) ๊ตฌํํ๊ธฐ (0) | 2023.03.24 |