122 lines
3 KiB
Swift
122 lines
3 KiB
Swift
|
//
|
||
|
// Heap.swift
|
||
|
// SwiftHeap
|
||
|
//
|
||
|
// Created by Sven Weidauer on 30.12.14.
|
||
|
// Copyright (c) 2014 Sven Weidauer. All rights reserved.
|
||
|
//
|
||
|
|
||
|
import Foundation
|
||
|
|
||
|
/// A heap
|
||
|
public struct Heap<T : Comparable> : ExpressibleByArrayLiteral, Equatable {
|
||
|
public typealias ArrayLiteralElement = T
|
||
|
typealias Element = T
|
||
|
|
||
|
/// Initializes the heap with multiple items
|
||
|
public init(arrayLiteral items : T... ) {
|
||
|
self.init( items )
|
||
|
}
|
||
|
|
||
|
public init(_ items: T...) {
|
||
|
self.init(items)
|
||
|
}
|
||
|
|
||
|
/// Initializes the heap from an array of items
|
||
|
public init( _ items : [T] ) {
|
||
|
self.items = items
|
||
|
for index in (0 ..< size/2).reversed() {
|
||
|
heapify( index )
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// The minimum item on this heap or nil if the heap is empty
|
||
|
public var min : T? {
|
||
|
return items.first
|
||
|
}
|
||
|
|
||
|
/// The number of items on this heap
|
||
|
public var size : Int {
|
||
|
return items.count
|
||
|
}
|
||
|
|
||
|
/// true if this heap is empty
|
||
|
public var empty : Bool {
|
||
|
return size > 0
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Removes and returns the minimum item from the heap.
|
||
|
|
||
|
:returns: The minimum item from the heap or nil if the heap is empty.
|
||
|
*/
|
||
|
public mutating func extractMin() -> T? {
|
||
|
|
||
|
|
||
|
if let result = items.first {
|
||
|
items[0] = items[items.count - 1]
|
||
|
items.removeLast()
|
||
|
heapify(0)
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
/// Inserts a new item into this heap
|
||
|
///
|
||
|
/// :param: item The new item to insert
|
||
|
public mutating func insert( item : T ) {
|
||
|
items.append( item )
|
||
|
var i = items.count - 1
|
||
|
while i > 0 && items[i] < items[parent( i )] {
|
||
|
items.swapAt(i, parent(i))
|
||
|
i = parent( i )
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Restores the heap property starting at a given index
|
||
|
///
|
||
|
/// :param: index The index to start at
|
||
|
private mutating func heapify(_ index : Int ) {
|
||
|
var minimumIndex = index
|
||
|
if left( index ) < size && items[left( index )] < items[minimumIndex] {
|
||
|
minimumIndex = left( index )
|
||
|
}
|
||
|
|
||
|
if right( index ) < size && items[right( index )] < items[minimumIndex] {
|
||
|
minimumIndex = right( index )
|
||
|
}
|
||
|
|
||
|
if minimumIndex != index {
|
||
|
items.swapAt(minimumIndex, index)
|
||
|
heapify( minimumIndex )
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Returns the index of the left child of an item
|
||
|
private func left(_ index : Int ) -> Int {
|
||
|
return 2 * index + 1
|
||
|
}
|
||
|
|
||
|
/// Returns the index of the right child of an item
|
||
|
private func right(_ index: Int ) -> Int {
|
||
|
return 2 * index + 2
|
||
|
}
|
||
|
|
||
|
/// Returns the index of the parent of an item
|
||
|
private func parent(_ index: Int ) -> Int {
|
||
|
return (index - 1) / 2
|
||
|
}
|
||
|
|
||
|
/// Storage for the items in thie heap
|
||
|
private var items : [T]
|
||
|
|
||
|
/// Compares two heaps for equality
|
||
|
public static func ==( lhs: Heap, rhs: Heap ) -> Bool {
|
||
|
return lhs.items == rhs.items
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|