Skip to content

Instantly share code, notes, and snippets.

@harshvishu
Created August 29, 2016 10:44
Show Gist options
  • Save harshvishu/5a1e106322fba7e9cd03701193a96bc4 to your computer and use it in GitHub Desktop.
Save harshvishu/5a1e106322fba7e9cd03701193a96bc4 to your computer and use it in GitHub Desktop.
Generic BinarySearchTree with map,filter,reduce
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