๊ธ€ ์ž‘์„ฑ์ž: ๊ฐœ๋ฐœํ•˜๋Š” ํ›ˆ์ด

ํž™ (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์„ ํ˜ธ์ถœํ•˜๋ฉด ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰ ์„œ๋ธŒํŠธ๋ฆฌ๋ถ€ํ„ฐ ์ˆœ์„œ๋Œ€๋กœ ํž™์„ ์žฌ๊ตฌ์„ฑํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

์ „์ฒด ์ฝ”๋“œ

 

 

 

GitHub - jeonyeohun/Data-Structures-In-Swift: ๐Ÿ‘ท๐Ÿป‍โ™‚๏ธ STL ์™œ ์—†์–ด.. ์Šค์œ„ํ”„ํŠธ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ

๐Ÿ‘ท๐Ÿป‍โ™‚๏ธ STL ์™œ ์—†์–ด.. ์Šค์œ„ํ”„ํŠธ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ. Contribute to jeonyeohun/Data-Structures-In-Swift development by creating an account on GitHub.

github.com

์ž๋ฃŒ๊ตฌ์กฐ ์‹œ๋ฆฌ์ฆˆ์˜ ์ฝ”๋“œ๋“ค์€ ์ด ๋ ˆํฌ์—์„œ ๋ชจ๋‘ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”!