Skip to content

Instantly share code, notes, and snippets.

@aessam
Last active April 1, 2016 23:44
Show Gist options
  • Save aessam/b61a0b5ab1a413998fcc to your computer and use it in GitHub Desktop.
Save aessam/b61a0b5ab1a413998fcc to your computer and use it in GitHub Desktop.
Simple Tree structure functions (add to tree, get max, get min, get tree width) for Swift with a playground result viewer
import Cocoa
import XCPlayground
// For some reason (May be because Swift is still beta) Xcode goes crazy when I change addTree to generics.
// Update Thanks to my friend Shady Said, I forgot to add compareable.
class Node<V : Comparable>{
var leftNode:Node?;
var rightNode:Node?;
var parent:Node?;
var value:V?;
init(parent: Node<V>){
self.parent = parent
}
init(){
}
}
func <<V>(lhs: Node<V>, rhs: Node<V>) -> Bool{
return lhs.value<rhs.value
}
func ><V>(lhs: Node<V>, rhs: Node<V>) -> Bool{
return lhs.value>rhs.value
}
// If the incoming value > then add to left, if the value is < add to right
// if the left/right has value will go recursively until empty node is found
func addToTree<V : Comparable>(tree: Node<V>, value:V){
if (tree.value != nil) {
var targetNode: Node<V>?
if tree.value > value{
if (tree.leftNode == nil){
tree.leftNode = Node<V>(parent: tree)
}
targetNode = tree.leftNode!
}
if tree.value < value{
if (tree.rightNode == nil){
tree.rightNode = Node<V>(parent: tree)
}
targetNode = tree.rightNode!
}
if let validNode = targetNode{
addToTree(validNode, value: value)
}
}else{
tree.value = value
}
}
// Get Max value in the tree by going to the far right side in the tree
func getMaxValueInTree<V>(tree: Node<V>)->V{
if let rn = tree.rightNode{
return getMaxValueInTree(rn)
}
return tree.value!
}
// Get Min value in the tree by going to the far left side in the tree
func getMinValueInTree<V>(tree: Node<V>)->V{
if let ln = tree.leftNode{
return getMinValueInTree(ln)
}
return tree.value!
}
// return how many steps does it take to go form root to the far left (Minimum value)
func rootToMin<V>(tree: Node<V>)->Int{
if let ln = tree.leftNode{
return rootToMin(ln)+1
}
return 0
}
// return how many steps does it take to go form root to the far right (Maximum value)
func rootToMax<V>(tree: Node<V>)->Int{
if let rn = tree.rightNode{
return rootToMin(rn)+1
}
return 0
}
// return the number of steps it takes to get from far east to far west nodes in the tree
func treeWidth<V>(tree: Node<V>)->Int{
return 1 + rootToMax(tree) + rootToMin(tree)
}
func getNodePath<V>(node: Node<V>)->String{
if let prnt = node.parent{
if prnt.leftNode === node{
return getNodePath(prnt) + "l"
}else{
return getNodePath(prnt) + "r"
}
}
return ""
}
func prepareForVisialViewer<V>(tree: Node<V>)-> Array<Array<String>>{
var res = Array<Array<String>>()
var next = Array<Node<V>>()
var current = Array<Node<V>>()
if let x = tree.rightNode{
current.append(x)
}
if let x = tree.leftNode{
current.append(x)
}
res.append(Array(["\(tree.value!)"]))
repeat{
var toAdd = Array<String>()
for node in current{
if let rn = node.rightNode{
next.append(rn)
}
if let ln = node.leftNode{
next.append(ln)
}
if let vl = node.value{
toAdd.append("\(getNodePath(node)) \(vl)")
}
}
res.append(toAdd)
current = next
next = Array<Node<V>>()
}while(current.count+next.count>0)
return res
}
func calcWidth(path: String)->CGFloat{
var tbl = ["r":1.0, "l":0.0]
var deepth = 0.0
// var part = 1/CGFloat(1<<(path.characters.count+1))
var c = 0
for char in path.characters{
if let v = tbl[String(char)]{
deepth += v*1/Double(1<<(c+1))
}
c+=1
}
deepth += 1/Double(1<<(path.characters.count+1))
return CGFloat(deepth)
}
// Testing
var root:Node<Int> = Node<Int>()
let rawTree = [16,8,24,4,12,20,28,2,6,10,14,18,22,26,30,1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31]
let tree = Node<Int>()
for v in rawTree{
addToTree(tree, value: v)
}
var treeForUI = prepareForVisialViewer(tree)
class CustomView: NSView {
override init(frame: NSRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func drawRect(dirtyRect: NSRect) {
for deepth in 0..<treeForUI.count{
var line = treeForUI[deepth]
for idxOfNode in 0..<line.count{
let txt = line[idxOfNode]
var arrOfParts = txt.componentsSeparatedByString(" ")
if arrOfParts.count>1{
let partValue = 1<<deepth
let boxWidth = self.frame.size.width/CGFloat(partValue)
for boxs in 0...partValue{
NSFrameRect(CGRectMake(boxWidth*CGFloat(boxs), self.frame.size.height - CGFloat((deepth+1)*16), boxWidth, 16))
}
"\(arrOfParts[1])".drawAtPoint(CGPointMake(calcWidth(arrOfParts[0] as String)*self.frame.size.width, self.frame.size.height - CGFloat((deepth+1)*16)), withAttributes: nil)
}else{
NSFrameRect(CGRectMake(1, self.frame.size.height - CGFloat((deepth+1)*16), self.frame.size.width-2, 16))
"\(arrOfParts[0])".drawAtPoint(CGPointMake(calcWidth("")*self.frame.size.width, self.frame.size.height - CGFloat((deepth+1)*16)), withAttributes: nil)
}
}
}
"Maximum Value in the tree is \(getMaxValueInTree(tree))".drawAtPoint(CGPointMake(0, 0),withAttributes: nil)
"Maximum Value in the tree is \(getMinValueInTree(tree))".drawAtPoint(CGPointMake(0, 16),withAttributes: nil)
"Distance from far left to far right is \(treeWidth(tree))".drawAtPoint(CGPointMake(0, 32),withAttributes: nil)
}
}
var view = CustomView(frame:
NSRect(x: 0, y: 0, width: 600, height: 150))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment