๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ–ฅ Computer Science/Data Structure

[Data Structure] ํž™(Heap)์ด๋ž€? (feat. Swift)

by Fomagran ๐Ÿ’ป 2021. 10. 15.
728x90
๋ฐ˜์‘ํ˜•

์•ˆ๋…•ํ•˜์„ธ์š” Foma ๐Ÿ’ป  ์ž…๋‹ˆ๋‹ค!

 

์š”์ฆ˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ณต๋ถ€ํ•˜๊ณ  ์žˆ๋Š”๋ฐ ๊ทธ ์ค‘ ํž™์†ŒํŠธ์— ๋Œ€ํ•ด ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

ํž™์†ŒํŠธ๋ฅผ ํ•˜๋ ค๋ฉด ํž™์ด๋ผ๋Š” ์ž๋ฃŒ๊ตฌ์กฐ๊ฐ€ ํ•„์š”ํ•˜๋”๋ผ๊ตฌ์š”.

 

๊ทธ๋ž˜์„œ ํž™์ด ๋ฌด์—‡์ด๊ณ  ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š”์ง€์— ๋Œ€ํ•ด ์ •๋ฆฌํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค!

 

๋ฐ”๋กœ ์‹œ์ž‘ํ• ๊ฒŒ์š”~


์™„์ „ ์ด์ง„ํŠธ๋ฆฌ(Complete Binary Tree)๋ž€? โ›“

 

๋จผ์ € ํž™์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ธฐ ์ „์— ์™„์ „์ด์ง„ํŠธ๋ฆฌ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์ด์œ ๋Š” ํž™์ด ์™„์ „์ด์ง„ํŠธ๋ฆฌ๋กœ ๋˜์–ด์žˆ๊ธฐ ๋–„๋ฌธ์ž…๋‹ˆ๋‹ค.

 

์™„์ „ ์ด์ง„ ํŠธ๋ฆฌ์—์„œ, ๋งˆ์ง€๋ง‰ ๋ ˆ๋ฒจ์„ ์ œ์™ธํ•˜๊ณ  ๋ชจ๋“  ๋ ˆ๋ฒจ์ด ์™„์ „ํžˆ ์ฑ„์›Œ์ ธ ์žˆ์œผ๋ฉฐ, ๋งˆ์ง€๋ง‰ ๋ ˆ๋ฒจ์˜ ๋ชจ๋“  ๋…ธ๋“œ๋Š” ๊ฐ€๋Šฅํ•œ ํ•œ ๊ฐ€์žฅ ์™ผ์ชฝ์— ์žˆ๋‹ค. ๋งˆ์ง€๋ง‰ ๋ ˆ๋ฒจ h ์—์„œ 1๋ถ€ํ„ฐ 2h-1 ๊ฐœ์˜ ๋…ธ๋“œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค. ์™„์ „ ์ด์ง„ ํŠธ๋ฆฌ๋Š” ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•ด ํšจ์œจ์ ์œผ๋กœ ํ‘œํ˜„ ๊ฐ€๋Šฅํ•˜๋‹ค. - ์œ„ํ‚ค ๋ฐฑ๊ณผ -

 

์ฆ‰, ๋งจ ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ์˜ ์ž์‹ ๋นผ๊ณ  ๋ชจ๋“  ๋…ธ๋“œ๊ฐ€ ๋‘๊ฐœ์”ฉ ์ž์‹์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•˜๋Š” ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.

 

์•„๋ž˜ ๊ทธ๋ฆผ์„ ๋ณด์‹œ๋ฉด ์ดํ•ดํ•˜๊ธฐ๊ฐ€ ์ˆ˜์›”ํ•˜์‹ค๊ฑฐ์—์š”!

 

 

์ถœ์ฒ˜: https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=jerrypoiu&logNo=221038260559


ํž™(Heap)์ด๋ž€? ๐Ÿ“˜

 

ํž™์€ ์ตœ๋Œ“๊ฐ’ ๋ฐ ์ตœ์†Ÿ๊ฐ’์„ ์ฐพ์•„๋‚ด๋Š” ์—ฐ์‚ฐ์„ ๋น ๋ฅด๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๊ณ ์•ˆ๋œ ์™„์ „์ด์ง„ํŠธ๋ฆฌ๋ฅผ ๊ธฐ๋ณธ์œผ๋กœ ํ•œ ์ž๋ฃŒ๊ตฌ์กฐ์ด๋‹ค. - ์œ„ํ‚ค ๋ฐฑ๊ณผ -

 

์ฆ‰, ์ตœ๋Œ“๊ฐ’๊ณผ ์ตœ์†Ÿ๊ฐ’์„ ๋น ๋ฅด๊ฒŒ ์ฐพ์•„๋‚ด๊ธฐ ์œ„ํ•œ ์ž๋ฃŒ๊ตฌ์กฐ ์ž…๋‹ˆ๋‹ค.

 

์ตœ๋Œ€ํž™(MaxHeap) ๐Ÿ‘๐Ÿป

 

์ตœ๋Œ€ํž™์€ ์ตœ๋Œ“๊ฐ’์„ ๋น ๋ฅด๊ฒŒ ์ฐพ์•„๋‚ด๊ธฐ ์œ„ํ•œ ์ž๋ฃŒ๊ตฌ์กฐ๋กœ,

 

๋ถ€๋ชจ๋…ธ๋“œ์˜ ํ‚ค๊ฐ’์ด ์ž์‹๋…ธ๋“œ์˜ ํ‚ค๊ฐ’๋ณด๋‹ค ํ•ญ์ƒ ํฐ ํž™์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

 

์ตœ์†Œํž™(MinHeap) ๐Ÿ‘Ž๐Ÿป

 

์ตœ์†Œํž™์€ ์ตœ๋Œ€ํž™๊ณผ ๋ฐ˜๋Œ€๋กœ ์ตœ์†Ÿ๊ฐ’์„ ๋น ๋ฅด๊ฒŒ ์ฐพ์•„๋‚ด๊ธฐ ์œ„ํ•œ ์ž๋ฃŒ๊ตฌ์กฐ๋กœ,

 

๋ถ€๋ชจ๋…ธ๋“œ์˜ ํ‚ค๊ฐ’์ด ์ž์‹๋…ธ๋“œ์˜ ํ‚ค๊ฐ’๋ณด๋‹ค ํ•ญ์ƒ ๋” ์ž‘์€ ํž™์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

 

ํŠน์ง•

 

๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.


์‹œ๊ฐ„๋ณต์žก๋„

 

ํž™์€ ์ „์ฒด ๋†’์ด๊ฐ€ logN์ž…๋‹ˆ๋‹ค.

 

๊ณ ๋กœ, ์‚ฝ์ž…์ด๋‚˜ ์‚ญ์ œ ์‹œ์— ๋…ธ๋“œ๋“ค์„ ์žฌ์ •๋ ฌ ํ•  ๋•Œ ์ตœ๋Œ€ logN์˜ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฐ๋‹ค.

 

๋ชจ๋“  N๊ฐœ์˜ ๋…ธ๋“œ๋“ค์ด ์ตœ๋Œ€ logN์˜ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฐ๋‹ค๋ฉด NlogN์˜ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๋ฏ€๋กœ ์‹œ๊ฐ„๋ณต์žก๋„๋Š” O(nlogn) ์ž…๋‹ˆ๋‹ค.


Heapify๋ž€? 

 

Heapify๋Š” ๋ง ๊ทธ๋Œ€๋กœ ํž™์˜ ์„ฑ์งˆ๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค.

 

์‚ฝ์ž…

 

์•„๋ž˜์™€ ๊ฐ™์ด ํŠน์ •ํ•œ ๊ฐ’์„ ๊ฐ€์ง„ ๋…ธ๋“œ๊ฐ€ ์ƒˆ๋กญ๊ฒŒ ๋“ค์–ด์™”์„ ๋•Œ ํž™์˜ ์„ฑ์งˆ์— ๋งž๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค.

 

๊ฐ„๋‹จํžˆ ๋งํ•˜๋ฉด ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์— ์ƒˆ๋กญ๊ฒŒ ๋“ค์–ด์˜จ ๋…ธ๋“œ๋ฅผ ์‚ฝ์ž…ํ•˜๊ณ  ๋ถ€๋ชจ ๋…ธ๋“œ์™€ ๋น„๊ตํ•˜๋ฉด์„œ ๋ฐ”๊ฟ”๊ฐ€์ฃผ๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค.

 

 

 

 

์‚ญ์ œ

 

์‚ญ์ œ๋Š” ๊ฐ€์žฅ ์ตœ๋Œ“๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ฃจํŠธ๋…ธ๋“œ๋ฅผ ์‚ญ์ œํ•ด์ค๋‹ˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  ๋ฃจํŠธ ๋…ธ๋“œ ์œ„์น˜์— ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์— ์žˆ๋Š” ๋…ธ๋“œ๋ฅผ ๋Œ€์‹ ํ•ด์ฃผ๊ณ  ์ž์‹๋…ธ๋“œ๋“ค์„ ๋น„๊ตํ•ด๊ฐ€๋ฉด์„œ ๋ฐ”๊ฟ”๊ฐ€๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค.

 

 

 

 


์ฝ”๋“œ ๊ตฌํ˜„

 

๋ณดํ†ต ํž™์œผ๋กœ ๋งŽ์ด ์“ฐ์ด๋Š” MaxHeap์„ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์ดˆ๊ธฐ์— ๋ฐฐ์—ด์ด ์ฃผ์–ด์ง„๋‹ค๋ฉด insert๋ฅผ ํ†ตํ•ด ํž™์„ ๋งŒ๋“œ๋Š” ์ดˆ๊ธฐํ™” ๊ณผ์ •์„ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋†“๊ณ 

 

๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉ๋  ๋ถ€๋ชจ,์ž์‹์˜ ์ธ๋ฑ์Šค๋ฅผ ์•Œ์•„๋‚ด๋Š” ํ•จ์ˆ˜์™€ ๋ถ€๋ชจ๋‚˜

 

์ž์‹์˜ ์œ ๋ฌด๋ฅผ ํ™•์ธํ•  ํ•จ์ˆ˜๋ฅผ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋†“๊ฒ ์Šต๋‹ˆ๋‹ค.

 

struct MaxHeap {
    var nodes:[Int] = []
    
    init(nodes:[Int]) {
        nodes.forEach {
            insert($0)
        }
    }
    
    private func getLeftChildIndex(_ parentIndex: Int) -> Int {
        return 2 * parentIndex + 1
    }
    private func getRightChildIndex(_ parentIndex: Int) -> Int {
        return 2 * parentIndex + 2
    }
    private func getParentIndex(_ childIndex: Int) -> Int {
        return (childIndex - 1) / 2
    }
    
    private func hasLeftChild(_ index: Int) -> Bool {
        return getLeftChildIndex(index) < nodes.count
    }
    private func hasRightChild(_ index: Int) -> Bool {
        return getRightChildIndex(index) < nodes.count
    }
    private func hasParent(_ index: Int) -> Bool {
        return getParentIndex(index) >= 0
    }
    
    ...

 

์‚ฝ์ž…

 

๋จผ์ € ์ƒˆ๋กœ์šด ๋…ธ๋“œ๋ฅผ ๊ธฐ์กด์˜ nodes์— ๋„ฃ์–ด์ค๋‹ˆ๋‹ค.

 

๋งจ ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ๋ถ€ํ„ฐ ์ฐจ๋ก€๋กœ ์œ„์˜ ๋ถ€๋ชจ์™€ ํ˜„์žฌ node๋ฅผ ๋น„๊ตํ•ด์ค๋‹ˆ๋‹ค.

 

๋งŒ์•ฝ ํ˜„์žฌ ๋…ธ๋“œ๊ฐ€ ๋” ํฌ๋‹ค๋ฉด ๋ถ€๋ชจ์™€ ์ž์‹ ์„ swapํ•ด์ค๋‹ˆ๋‹ค.

 

์ด๊ฒƒ์„ root๋…ธ๋“œ๊ฐ€ ๋˜๊ฑฐ๋‚˜ ๋ถ€๋ชจ๊ฐ€ ๋” ํด ๋•Œ๊นŒ์ง€ heapify ๊ณผ์ •์„ ์œ„๋กœ ๋ฐ˜๋ณตํ•ฉ๋‹ˆ๋‹ค.

 

 mutating private func heapifyUp() {
        var index = nodes.count - 1
        while hasParent(index) && nodes[getParentIndex(index)] < nodes[index] {
            nodes.swapAt(getParentIndex(index),index)
            index = getParentIndex(index)
        }
    }
    
    mutating func insert(_ node:Int) {
        nodes.append(node)
        heapifyUp()
    }

 

์‚ญ์ œ

 

nodes๊ฐ€ ์•„๋ฌด๊ฒƒ๋„ ์—†๋‹ค๋ฉด ์‹คํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

๋งŒ์•ฝ ์กด์žฌํ•œ๋‹ค๋ฉด ๊ฐ€์žฅ ์ฒซ๋ฒˆ์งธ์™€ ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰ ๋ฒˆ์งธ ๋…ธ๋“œ๋ฅผ ์„œ๋กœ ๋ฐ”๊ฟ”์ฃผ๊ณ 

 

๊ฐ€์žฅ ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ๋ฅผ ์‚ญ์ œํ•ด์ค๋‹ˆ๋‹ค. (์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ฐ€์žฅ ํฐ ๊ฐ’์„ ์‚ญ์ œํ•œ ๊ฒƒ๊ณผ ๋˜‘๊ฐ™๊ฒ ์ฃ ?)

 

๊ทธ๋ฆฌ๊ณค ๊ฐ€์žฅ ์œ„(0)๋ถ€ํ„ฐ ์ฐจ๋ก€๋กœ ์ž์‹๋“ค์ด ๋” ์ž‘์„ ๋•Œ๊นŒ์ง€ heapify๋ฅผ ์•„๋ž˜๋กœ ๋ฐ˜๋ณตํ•ด์ค๋‹ˆ๋‹ค.

 

  mutating private func heapifyDown() {
        var index = 0
        while hasLeftChild(index) {
            let leftIndex:Int = getLeftChildIndex(index)
            let rightIndex:Int = getRightChildIndex(index)
            var biggerChildIndex = leftIndex
            if hasRightChild(index) && nodes[leftIndex] < nodes[rightIndex] {
                biggerChildIndex = rightIndex
            }
            
            if nodes[index] > nodes[biggerChildIndex] {
                break
            } else {
                nodes.swapAt(index, biggerChildIndex)
            }
            index = biggerChildIndex
        }
    }
    
    mutating func remove()  {
        if nodes.isEmpty {
            return
        }
        nodes.swapAt(0, nodes.count - 1)
        nodes.removeLast()
        heapifyDown()
    }

 

 

์‚ฝ์ž…ํ•˜๊ณ  ์‚ญ์ œ๋ฅผ ํ•˜๋Š” ๊ณผ์ •์„ ์ถœ๋ ฅํ•ด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

 

     	var heap = MaxHeap(nodes: [1,5,3]) //[5,1,3]
        heap.insert(4) //[5,4,3,1]
        heap.insert(2) //[5,4,3,1,2]
        heap.insert(1) //[5,4,3,1,2,1]
        heap.insert(2) //[5,4,3,1,2,1,2]
        heap.remove() //[4,2,3,1,2,1]
        heap.remove() //[3,2,1,1,2]
        heap.remove() //[2,2,1,1]
        heap.insert(7) //[7, 2, 1, 1, 2]
        heap.insert(5) //[7, 2, 5, 1, 2, 1]

์ „์ฒด ์ฝ”๋“œ

 

 

 


Reference

 

์•„๋ž˜ ๋ธ”๋กœ๊ทธ๋ฅผ ์ฐธ๊ณ ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

 

Swift Data Structures: Heap

What is a Heap?

medium.com

 

728x90
๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€