diff --git a/contents/tree_traversal/code/swift/tree.swift b/contents/tree_traversal/code/swift/tree.swift new file mode 100644 index 000000000..e286c8fb0 --- /dev/null +++ b/contents/tree_traversal/code/swift/tree.swift @@ -0,0 +1,104 @@ +class Node { + var value: Int + var children: [Node]? + + init(value: Int, children: [Node]) { + self.value = value + self.children = children + } +} + +func createTree(numRows: Int, numChildren: Int) -> Node { + let node = Node(value: numRows, children: []) + + if numRows > 0 { + for _ in 1...numChildren { + let child = createTree(numRows: numRows-1, numChildren: numChildren) + node.children?.append(child) + } + } + + return node +} + +func dfsRecursive(node: Node) { + print(node.value) + + for child in node.children! { + dfsRecursive(node: child) + } +} + +func dfsRecursivePostOrder(node: Node) { + for child in node.children! { + dfsRecursivePostOrder(node: child) + } + + print(node.value) +} + +func dfsRecursiveInOrderBinary(node: Node) { + if node.children?.count == 2 { + dfsRecursiveInOrderBinary(node: node.children![0]) + print(node.value) + dfsRecursiveInOrderBinary(node: node.children![1]) + } else if node.children?.count == 1 { + dfsRecursiveInOrderBinary(node: node.children![0]) + print(node.value) + } else if node.children?.count == 0 { + print(node.value) + } else { + print("Not a binary tree!") + } +} + +func dfsStack(node: Node) { + var stack = [node] + var temp: Node + + while stack.count > 0 { + temp = stack.popLast()! + print(temp.value) + + for child in temp.children! { + stack.append(child) + } + } +} + +func bfsQueue(node: Node) { + var queue = [node] + var temp: Node + + while queue.count > 0 { + temp = queue.remove(at: 0) + print(temp.value) + + for child in temp.children! { + queue.append(child) + } + } +} + +func main() { + let root = createTree(numRows: 3, numChildren: 3) + + print("Using recursive DFS:") + dfsRecursive(node: root) + + print("Using recursive postorder DFS:") + dfsRecursivePostOrder(node: root) + + print("Using stack-based DFS:") + dfsStack(node: root) + + print("Using queue-based BFS:") + bfsQueue(node: root) + + let rootBinary = createTree(numRows: 3, numChildren: 2) + + print("Using In-order DFS:") + dfsRecursiveInOrderBinary(node: rootBinary) +} + +main() diff --git a/contents/tree_traversal/tree_traversal.md b/contents/tree_traversal/tree_traversal.md index c33c5bb83..22cdb26e7 100644 --- a/contents/tree_traversal/tree_traversal.md +++ b/contents/tree_traversal/tree_traversal.md @@ -26,6 +26,8 @@ This has not been implemented in your chosen language, so here is the Julia code [import:4-7, lang:"rust"](code/rust/tree.rs) {% sample lang="hs"%} [import:1-3, lang:"haskell"](code/haskell/TreeTraversal.hs) +{% sample lang="swift"%} +[import:1-9, lang:"swift"](code/swift/tree.swift) {% endmethod %} Because of this, the most straightforward way to traverse the tree might be recursive. This naturally leads us to the Depth-First Search (DFS) method: @@ -54,6 +56,8 @@ Because of this, the most straightforward way to traverse the tree might be recu [import:9-15 lang:"rust"](code/rust/tree.rs) {% sample lang="hs"%} [import:5-6, lang:"haskell"](code/haskell/TreeTraversal.hs) +{% sample lang="swift"%} +[import:24-30, lang:"swift"](code/swift/tree.swift) {% endmethod %} At least to me, this makes a lot of sense. We fight recursion with recursion! First, we first output the node we are on and then we call `DFS_recursive(...)` on each of its children nodes. This method of tree traversal does what its name implies: it goes to the depths of the tree first before going through the rest of the branches. In this case, the ordering looks like: @@ -92,6 +96,8 @@ This has not been implemented in your chosen language, so here is the Julia code [import:18-26, lang:"julia"](code/julia/Tree.jl) {% sample lang="hs"%} [import:8-9, lang:"haskell"](code/haskell/TreeTraversal.hs) +{% sample lang="swift"%} +[import:32-38, lang:"swift"](code/swift/tree.swift) {% endmethod %}
@@ -125,6 +131,8 @@ This has not been implemented in your chosen language, so here is the Julia code [import:28-43, lang:"julia"](code/julia/Tree.jl) {% sample lang="hs"%} [import:11-15, lang:"haskell"](code/haskell/TreeTraversal.hs) +{% sample lang="swift"%} +[import:40-53, lang:"swift"](code/swift/tree.swift) {% endmethod %}
@@ -167,6 +175,8 @@ In code, it looks like this: {% sample lang="hs"%} This has not been implemented in your chosen language, so here is the Julia code [import:45-56, lang:"julia"](code/julia/Tree.jl) +{% sample lang="swift"%} +[import:55-67, lang:"swift"](code/swift/tree.swift) {% endmethod %} All this said, there are a few details about DFS that might not be idea, depending on the situation. For example, if we use DFS on an incredibly long tree, we will spend a lot of time going further and further down a single branch without searching the rest of the data structure. In addition, it is not the natural way humans would order a tree if asked to number all the nodes from top to bottom. I would argue a more natural traversal order would look something like this: @@ -200,6 +210,8 @@ And this is exactly what Breadth-First Search (BFS) does! On top of that, it can [import:26-34, lang:"rust"](code/rust/tree.rs) {% sample lang="hs"%} [import:17-20, lang:"haskell"](code/haskell/TreeTraversal.hs) +{% sample lang="swift"%} +[import:69-81, lang:"swift"](code/swift/tree.swift) {% endmethod %} ## Example Code @@ -235,6 +247,8 @@ The code snippets were taken from this [Scratch project](https://scratch.mit.edu [import, lang:"rust"](code/rust/tree.rs) {% sample lang="hs"%} [import, lang:"haskell"](code/haskell/TreeTraversal.hs) +{% sample lang="swift"%} +[import, lang:"swift"](code/swift/tree.swift) {% endmethod %}