Trees
Preorder Traversal
Visit the root before each subtree, producing root-left-right order.
Algorithm
The canonical tree is 4(2(1,3),6(5,7)), so this Swift DSA
implementation can be compared directly with the rest of the DSA track.
preorder
Preorder records the current node before visiting left and right subtrees.
Basic Implementation
basic.swift
Replay: real traced execution (multi-file project)
final class Node {
let value: Int
var left: Node?
var right: Node?
init(_ value: Int, _ left: Node? = nil, _ right: Node? = nil) { self.value = value; self.left = left; self.right = right }
}
func render(_ node: Node?) -> String {
guard let node = node else { return "_" }
if node.left == nil && node.right == nil { return String(node.value) }
return "\(node.value)(\(render(node.left)),\(render(node.right)))"
}
func sampleTree() -> Node {
return Node(4, Node(2, Node(1), Node(3)), Node(6, Node(5), Node(7)))
}
func listString(_ values: [Int]) -> String { return "[" + values.map(String.init).joined(separator: ", ") + "]" }
func preorder(_ node: Node?, _ output: inout [Int]) { guard let node = node else { return }; output.append(node.value); preorder(node.left, &output); preorder(node.right, &output) }
var output: [Int] = []
preorder(sampleTree(), &output)
print(listString(output))
tree ← 4(2(1,3),6(5,7)), output ← []
1final class Node {2 let value: Intvalues this step4(2(1,3),6(5,7))tree[]outputoutput ← [4]
15func listString(_ values: [Int]) -> String { return "[" + values.map(String.init).joined(separator: ", ") + "]" }16func preorder(_ node: Node?, _ output: inout [Int]) { guard let node = node else { return }; output.append(node.value); preorder(node.left, &output); preorder(node.right, &output) }17var output: [Int] = []values this step[] → [4]output4nodeoutput ← [4, 2]
15func listString(_ values: [Int]) -> String { return "[" + values.map(String.init).joined(separator: ", ") + "]" }16func preorder(_ node: Node?, _ output: inout [Int]) { guard let node = node else { return }; output.append(node.value); preorder(node.left, &output); preorder(node.right, &output) }17var output: [Int] = []values this step[4] → [4, 2]output2nodeoutput ← [4, 2, 1]
15func listString(_ values: [Int]) -> String { return "[" + values.map(String.init).joined(separator: ", ") + "]" }16func preorder(_ node: Node?, _ output: inout [Int]) { guard let node = node else { return }; output.append(node.value); preorder(node.left, &output); preorder(node.right, &output) }17var output: [Int] = []values this step[4, 2] → [4, 2, 1]output1nodeoutput ← [4, 2, 1, 3]
15func listString(_ values: [Int]) -> String { return "[" + values.map(String.init).joined(separator: ", ") + "]" }16func preorder(_ node: Node?, _ output: inout [Int]) { guard let node = node else { return }; output.append(node.value); preorder(node.left, &output); preorder(node.right, &output) }17var output: [Int] = []values this step[4, 2, 1] → [4, 2, 1, 3]output3nodeoutput ← [4, 2, 1, 3, 6]
15func listString(_ values: [Int]) -> String { return "[" + values.map(String.init).joined(separator: ", ") + "]" }16func preorder(_ node: Node?, _ output: inout [Int]) { guard let node = node else { return }; output.append(node.value); preorder(node.left, &output); preorder(node.right, &output) }17var output: [Int] = []values this step[4, 2, 1, 3] → [4, 2, 1, 3, 6]output6nodeoutput ← [4, 2, 1, 3, 6, 5]
15func listString(_ values: [Int]) -> String { return "[" + values.map(String.init).joined(separator: ", ") + "]" }16func preorder(_ node: Node?, _ output: inout [Int]) { guard let node = node else { return }; output.append(node.value); preorder(node.left, &output); preorder(node.right, &output) }17var output: [Int] = []values this step[4, 2, 1, 3, 6] → [4, 2, 1, 3, 6, 5]output5nodeoutput ← [4, 2, 1, 3, 6, 5, 7]
15func listString(_ values: [Int]) -> String { return "[" + values.map(String.init).joined(separator: ", ") + "]" }16func preorder(_ node: Node?, _ output: inout [Int]) { guard let node = node else { return }; output.append(node.value); preorder(node.left, &output); preorder(node.right, &output) }17var output: [Int] = []values this step[4, 2, 1, 3, 6, 5] → [4, 2, 1, 3, 6, 5, 7]output7nodeprint(listString(output))
18preorder(sampleTree(), &output)19print(listString(output))values this step[4, 2, 1, 3, 6, 5, 7]output
Complexity
- Time: O(n)
- Space: O(h) recursion stack
Implementation notes
final class Nodegives each tree node reference semantics, withlet value: Intand optional child linksleft: Node?andright: Node?.preorder(_ node: Node?, _ output: inout [Int])accepts an optional node and mutates the caller's output array throughinout.- The base case is
guard let node = node else { return }, sonilchild links return without adding a sentinel value. - The function appends before recursion:
output.append(node.value), thenpreorder(node.left, &output), thenpreorder(node.right, &output). var output: [Int] = []starts empty, andpreorder(sampleTree(), &output)walks the canonical4(2(1,3),6(5,7))tree.- The trace shows output growing step by step:
[4],[4, 2],[4, 2, 1],[4, 2, 1, 3], then the right subtree[4, 2, 1, 3, 6, 5, 7]. listString(_:)formats theIntarray with comma separators, soprint(listString(output))writes[4, 2, 1, 3, 6, 5, 7].