λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
πŸ–₯ Computer Science/Algorithm

[Algorithm] νž™ μ •λ ¬(HeapSort)μ΄λž€? (feat.Swift)

by Fomagran πŸ’» 2021. 10. 19.
728x90
λ°˜μ‘ν˜•

μ•ˆλ…•ν•˜μ„Έμš” Foma πŸ’» μž…λ‹ˆλ‹€!

 

μ €λ²ˆ μ‹œκ°„μ— νž™μ΄λž€ μžλ£Œκ΅¬μ‘°μ— λŒ€ν•΄μ„œ μ•Œμ•„λ³΄μ•˜λŠ”λ°μš”. (ν˜Ήμ‹œλΌλ„ μ•ˆλ³΄μ‹  뢄은 μ—¬κΈ° μ—μ„œ 보고 μ™€μ£Όμ„Έμš”!)

 

μ˜€λŠ˜μ€ νž™μ„ μ΄μš©ν•΄μ„œ 정렬을 ν•˜λŠ” νž™μ†ŒνŠΈμ— λŒ€ν•΄μ„œ μ•Œμ•„λ³΄λ €κ³  ν•©λ‹ˆλ‹€!

λ°”λ‘œ μ‹œμž‘ν• κ²Œμš”~


νž™ μ •λ ¬((HeapSort)μ΄λž€? 🧐

 

νž™ μ •λ ¬(Heap sort)μ΄λž€ μ΅œλŒ€ νž™ νŠΈλ¦¬λ‚˜ μ΅œμ†Œ νž™ 트리λ₯Ό ꡬ성해 정렬을 ν•˜λŠ” λ°©λ²•μœΌλ‘œμ„œ, λ‚΄λ¦Όμ°¨μˆœ 정렬을 μœ„ν•΄μ„œλŠ” μ΅œλŒ€ νž™μ„ κ΅¬μ„±ν•˜κ³  μ˜€λ¦„μ°¨μˆœ 정렬을 μœ„ν•΄μ„œλŠ” μ΅œμ†Œ νž™μ„ κ΅¬μ„±ν•˜λ©΄ λœλ‹€. - μœ„ν‚€ λ°±κ³Ό -

 

즉, νž™μ„ μ΄μš©ν•΄μ„œ 정렬을 ν•˜λŠ” λ°©μ‹μ΄μ—μš”.


νž™ μ •λ ¬ κ³Όμ • πŸ”¨

 

νž™ μ •λ ¬ 과정은 νž™μ—μ„œ μ‚­μ œλ₯Ό κ΅¬ν˜„ν•  λ•Œμ™€ λ˜‘κ°™μ•„μš”.

 

μ‚­μ œκ³Όμ •μ΄ μ•„λž˜μ™€ κ°™μ€λ°μš”.

 

 

 

 

λͺ¨λ“  λ…Έλ“œλ₯Ό μ‚­μ œν•˜κ³  배열에 μ°¨λ‘€λ‘œ μŒ“κ²Œλ˜λ©΄ μ–΄λ–»κ²Œ λ κΉŒμš”?

 

μ΅œλŒ€νž™μ΄λΌλ©΄ κ°€μž₯ 큰 μˆ«μžκ°€ μ°¨λ‘€λ‘œ μŒ“μ΄κ²Œ 될거고 μ΅œμ†Œνž™μ΄λΌλ©΄ κ°€μž₯ μž‘μ€ μˆ«μžκ°€ μ°¨λ‘€λ‘œ μŒ“μ΄κ²Œ 되겠죠?

 

즉, μ˜€λ¦„μ°¨μˆœ ν˜Ήμ€ λ‚΄λ¦Όμ°¨μˆœμœΌλ‘œ μ •λ ¬ν•  수 μžˆκ²Œλ˜λŠ” 것이죠.

 

μ•„λž˜λŠ” νž™μ •λ ¬μ„ ν•΄λ‚˜κ°€λŠ” κ³Όμ •μ΄μ—μš”.

 

좜처:μœ„ν‚€λ°±κ³Ό


μ‹œκ°„λ³΅μž‘λ„

 

νž™ μ •λ ¬μ˜ μ‹œκ°„λ³΅μž‘λ„λŠ” N개의 λ…Έλ“œλ₯Ό μ΅œλŒ€ logN번 Heapifyν•˜λŠ” 과정을 거치기 λ•Œλ¬Έμ— O(nlogn)μž…λ‹ˆλ‹€.


μ½”λ“œ κ΅¬ν˜„

 

λ¨Όμ € μ €λ²ˆ μ‹œκ°„μ— λ§Œλ“€μ–΄λ†“μ•˜λ˜ MaxHeap을 κ°€μ Έμ˜€κ² μŠ΅λ‹ˆλ‹€.

 

import Foundation
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
}
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()
}
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()
}
}
view raw MaxHeap.swift hosted with ❀ by GitHub

 

μ½”λ“œλ‘œ κ΅¬ν˜„ν•˜λŠ” 것은 κ°„λ‹¨ν•©λ‹ˆλ‹€.

 

μš°μ„  μ£Όμ–΄μ§„ 배열을 νž™μœΌλ‘œ λ§Œλ“€μ–΄μ£Όκ³ , 배열에 μžˆλŠ” λͺ¨λ“  숫자λ₯Ό μ—†μ• μ€λ‹ˆλ‹€.

 

그리곀 heap에 μžˆλŠ” μ΅œλŒ“κ°’μ„ μ°¨λ‘€λ‘œ 배열에 λ„£μ–΄μ£Όλ©΄μ„œ μ‚­μ œν•˜λŠ” 과정을 거치면 정렬이 μ™„μ„±λ©λ‹ˆλ‹€.

 

var numbers:[Int] = [4,1,7,5,3,2,6]

extension Array where Element == Int{
    mutating func sortByHeap(descending:Bool) -> [Element] {
        var heap = MaxHeap(nodes: self)
        self.removeAll()
        for _ in heap.nodes {
            if let max = heap.nodes.first {
                if descending {
                    self.append(max)
                }else {
                    self.insert(max, at: 0)
                }
            }
            heap.remove()
        }
        return self
    }
}

numbers.sortByHeap(descending: false)//[1,2,3,4,5,6,7]
numbers.sortByHeap(descending: true)//[7,6,5,4,3,2,1]
728x90
λ°˜μ‘ν˜•

λŒ“κΈ€