This is heapsort in a Swift playground. I needed a stable sort, so naturally I wrote an… unstable sort.

Of course, you can just use sort() or sorted(), but if you are inclined to roll your own, the Swifty way to do it is to create an extension. Note that an Array extension with a Generic Where Clause is needed to make element comparisons > < == work.

//: Playground - noun: a place where people can play

import Cocoa

// var elements = [0, 6, 0, 6, 4, 0, 6, 0, 6, 0, 4, 3, 0, 1, 5, 1, 2, 4, 2, 4]

var elements = [10, 6, 0, 1, 2, 5, 4, 3, 7, 8, 9]

extension Array where Element: Comparable {
    func heapSorted() -> Array {
        var r = self
        
        func parent(_ i: Int) -> Int {
            return ((i+1) / 2) - 1
        }
        
        func leftChild(_ i: Int) -> Int {
            return ((i + 1) * 2) - 1
        }
        
        func rightChild(_ i: Int) -> Int {
            return leftChild(i) + 1
        }
        
        func descend(i: Int, limit: Int) {
            let lindex = leftChild(i)
            let rindex = rightChild(i)
            if rindex > limit || r[lindex] > r[rindex] {
                if lindex <= limit && r[lindex] > r[i] {
                    (r[lindex],r[i]) = (r[i],r[lindex])
                    descend(i: lindex, limit: limit)
                }
            } else if rindex <= limit {
                if r[rindex] > r[i] {
                    (r[rindex],r[i]) = (r[i],r[rindex])
                    descend(i: rindex, limit: limit)
                }
            }
        }
        
        func maxHeapify() {
            let lastParent = parent(r.count - 1)
            for i in (0...lastParent).reversed() {
                descend(i: i, limit: r.count - 1)
            }
        }
        
        func sortFromHeap() {
            for i in (1..<r.count).reversed() {
                (r[0],r[i]) = (r[i],r[0])
                descend(i: 0, limit: i-1)
            }
        }
        
        maxHeapify()
        sortFromHeap()
        
        return r
    }
}

elements.heapSorted().forEach{print($0, terminator: " ")}
print()

On to writing mergesort (stable).

Sigh.

Leave a Reply