Created
August 29, 2016 10:44
-
-
Save harshvishu/5a1e106322fba7e9cd03701193a96bc4 to your computer and use it in GitHub Desktop.
Generic BinarySearchTree with map,filter,reduce
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
public class BinarySearchTree<T: Comparable>{ | |
private (set) public var value: T | |
private (set) public var parent: BinarySearchTree? | |
private (set) public var left: BinarySearchTree? | |
private (set) public var right: BinarySearchTree? | |
public init(value: T){ | |
self.value = value | |
} | |
convenience init(array: [T]){ | |
precondition(array.count > 0) | |
self.init(value: array.first!) | |
for v in array.dropFirst(){ | |
insert(v,parent: self) | |
} | |
} | |
public var isRoot: Bool { | |
return parent == nil | |
} | |
public var isLeaf: Bool { | |
return left == nil && right == nil | |
} | |
public var isLeftChild: Bool{ | |
return parent?.left === self | |
} | |
public var isRightChild: Bool{ | |
return parent?.right === self | |
} | |
public var hasLeftChild: Bool{ | |
return left != nil | |
} | |
public var hasRightChild: Bool{ | |
return right != nil | |
} | |
public var hasAnyChild: Bool{ | |
return hasLeftChild || hasRightChild | |
} | |
public var hasBothChildren: Bool{ | |
return hasLeftChild && hasRightChild | |
} | |
public var count: Int{ | |
return 1 + (left?.count ?? 0) + (right?.count ?? 0) | |
} | |
// Insertion | |
public func insert(value: T){ | |
insert(value, parent: self) | |
} | |
private func insert(value: T, parent: BinarySearchTree?){ | |
if value < self.value { | |
if let left = left{ | |
left.insert(value, parent: left) | |
}else { | |
left = BinarySearchTree(value: value) | |
left?.parent = parent | |
} | |
}else{ | |
if let right = right{ | |
right.insert(value, parent: right) | |
}else{ | |
right = BinarySearchTree(value: value) | |
right?.parent = parent | |
} | |
} | |
} | |
/*public func search(value: T) -> BinarySearchTree?{ | |
if value < self.value{ | |
return left?.search(value) | |
}else if value > self.value{ | |
return right?.search(value) | |
}else{ | |
return self | |
} | |
}*/ | |
public func search(value: T) -> BinarySearchTree?{ | |
var node: BinarySearchTree? = self | |
while case let n? = node{ | |
if value < n.value { | |
node = n.left | |
}else if value > n.value{ | |
node = n.right | |
} else{ | |
return node | |
} | |
} | |
return nil | |
} | |
public func traverseInOrder(@noescape process: T -> Void) { | |
left?.traverseInOrder(process) | |
process(value) | |
right?.traverseInOrder(process) | |
} | |
public func traversePreOrder(@noescape process: T -> Void) { | |
process(value) | |
left?.traversePreOrder(process) | |
right?.traversePreOrder(process) | |
} | |
public func traversePostOrder(@noescape process: T -> Void) { | |
left?.traversePostOrder(process) | |
right?.traversePostOrder(process) | |
process(value) | |
} | |
public func map(@noescape formula: T -> T) -> [T]{ | |
var a = [T]() | |
if let left = left { | |
a += left.map(formula) | |
} | |
a.append(formula(value)) | |
if let right = right{ | |
a += right.map(formula) | |
} | |
return a | |
} | |
public func filter(@noescape predicate: T -> Bool) -> [T]{ | |
var a = [T]() | |
if let left = left { | |
a += left.filter(predicate) | |
} | |
if predicate(value){ | |
a.append(value) | |
} | |
if let right = right{ | |
a += right.filter(predicate) | |
} | |
return a | |
} | |
public func reduce<U>(seed:U,combiner:(U,T) -> U) -> U{ | |
var current = seed | |
if let left = left{ | |
current = left.reduce(current, combiner: combiner) | |
} | |
current = combiner(current,value) | |
if let right = right{ | |
current = right.reduce(current, combiner: combiner) | |
} | |
return current | |
} | |
public var height: Int{ | |
guard hasAnyChild else{return 0} | |
let leftHeight = left?.height ?? 0 | |
let rightHeight = right?.height ?? 0 | |
return 1 + max(leftHeight , rightHeight) | |
} | |
} | |
extension BinarySearchTree: CustomStringConvertible { | |
public var description: String { | |
var s = "" | |
if let left = left { | |
s += "(\(left.description)) <- " | |
} | |
s += "\(value)" | |
if let right = right { | |
s += " -> (\(right.description))" | |
} | |
return s | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment