[Algorithm] Heap

Martin Kim·2023년 4월 2일

Algorithm

목록 보기
2/2

2024.02.12 수정
아래 글 구현으로 하면 일부 문제를 통과할 수 없습니다.
ex) https://www.acmicpc.net/problem/1162
쉬프트 다운 할 때 sorted, filter를 연속으로 사용하는 부분에서 시간 초과의 원인이 되네요
다음과 같이 수정하면 통과할 수 있습니다.

final class Heap<T: Comparable> {
    private var nodes: [T] = []
    private let sort: (T, T) -> Bool
    
    init(_ sort: @escaping ((T, T) -> Bool)) {
        self.sort = sort
    }
    
    var isEmpty: Bool {
        nodes.isEmpty
    }
    
    func insert(_ data: T) {
        var index = nodes.count
        nodes.append(data)
        
        while index >= 0, sort(nodes[index], nodes[(index-1) / 2]) {
            nodes.swapAt(index, (index - 1) / 2)
            index = (index-1) / 2
        }
    }
    
    func delete() -> T {
        if nodes.count == 1 {
            return nodes.removeLast()
        }
        
        let data = nodes.first!
        nodes.swapAt(0, nodes.count - 1)
        nodes.removeLast()
        
        let limit = nodes.count
        var index = 0
        
        while index < limit {
            let leftChild = index * 2 + 1
            let rightChild = leftChild + 1
            var candidate = index

            if leftChild < limit && sort(nodes[leftChild], nodes[candidate]) {
                candidate = leftChild
            }

            if rightChild < limit && sort(nodes[rightChild], nodes[candidate]) {
                candidate = rightChild
            }

            if candidate == index {
                break
            }
            nodes.swapAt(index, candidate)
            index = candidate
        }
        
        return data
    }
}

Swift로 우선순위 큐를 구현하려면 직접 힙을 구현해야한다.
여기 Swift로 구현한 힙이 있습니다. 찾은 자료중 가장 깔끔한것 같아요.

final class Heap<T: Comparable> {
    private var nodes: [T] = []
    private let sort: (T, T) -> Bool
    
    init(sort: @escaping ((T, T) -> Bool)) {
        self.sort = sort
    }
    
    var isEmpty: Bool {
        nodes.isEmpty
    }
    
    func insert(_ data: T) {
        var index = nodes.count
        nodes.append(data)
        
        while index >= 0, sort(nodes[index], nodes[(index-1) / 2]) {
            nodes.swapAt(index, (index - 1) / 2)
            index = (index-1) / 2
        }
    }
    
    func delete() -> T {
        if nodes.count == 1 {
            return nodes.removeFirst()
        }
        
        let data = nodes.first!
        nodes.swapAt(0, nodes.count - 1)
        nodes.removeLast()
        
        let limit = nodes.count
        var index = 0
        
        while index < limit {
            let leftChild = index * 2 + 1
            let rightChild = leftChild + 1
            
            let children = [leftChild, rightChild]
            .filter { $0 < limit && sort(nodes[$0], nodes[index]) }
            .sorted { sort(nodes[$0], nodes[$1]) }
            
            if children.isEmpty { break }
            nodes.swapAt(index, children.first!)
            index = children.first!
        }
        
        return data
    }
}

let heap = Heap<Int>(sort: < )
profile
학생입니다

0개의 댓글