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 Kotlin 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.kt
Replay: real traced execution (multi-file project)
class Node(val value: Int, var left: Node? = null, var right: Node? = null)
fun render(node: Node?): String {
if (node == null) return "_"
if (node.left == null && node.right == null) return node.value.toString()
return "${node.value}(${render(node.left)},${render(node.right)})"
}
fun sampleTree() = Node(4, Node(2, Node(1), Node(3)), Node(6, Node(5), Node(7)))
fun listString(values: List<Int>) = values.joinToString(", ", "[", "]")
fun preorder(node: Node?, output: MutableList<Int>) { if (node == null) return; output.add(node.value); preorder(node.left, output); preorder(node.right, output) }
fun main() { val output = mutableListOf<Int>(); preorder(sampleTree(), output); println(listString(output)) }
tree ← 4(2(1,3),6(5,7)), output ← []
1class Node(val value: Int, var left: Node? = null, var right: Node? = null)2fun render(node: Node?): String {values this step4(2(1,3),6(5,7))tree[]outputoutput ← [4]
8fun listString(values: List<Int>) = values.joinToString(", ", "[", "]")9fun preorder(node: Node?, output: MutableList<Int>) { if (node == null) return; output.add(node.value); preorder(node.left, output); preorder(node.right, output) }10fun main() { val output = mutableListOf<Int>(); preorder(sampleTree(), output); println(listString(output)) }values this step[] → [4]output4nodeoutput ← [4, 2]
8fun listString(values: List<Int>) = values.joinToString(", ", "[", "]")9fun preorder(node: Node?, output: MutableList<Int>) { if (node == null) return; output.add(node.value); preorder(node.left, output); preorder(node.right, output) }10fun main() { val output = mutableListOf<Int>(); preorder(sampleTree(), output); println(listString(output)) }values this step[4] → [4, 2]output2nodeoutput ← [4, 2, 1]
8fun listString(values: List<Int>) = values.joinToString(", ", "[", "]")9fun preorder(node: Node?, output: MutableList<Int>) { if (node == null) return; output.add(node.value); preorder(node.left, output); preorder(node.right, output) }10fun main() { val output = mutableListOf<Int>(); preorder(sampleTree(), output); println(listString(output)) }values this step[4, 2] → [4, 2, 1]output1nodeoutput ← [4, 2, 1, 3]
8fun listString(values: List<Int>) = values.joinToString(", ", "[", "]")9fun preorder(node: Node?, output: MutableList<Int>) { if (node == null) return; output.add(node.value); preorder(node.left, output); preorder(node.right, output) }10fun main() { val output = mutableListOf<Int>(); preorder(sampleTree(), output); println(listString(output)) }values this step[4, 2, 1] → [4, 2, 1, 3]output3nodeoutput ← [4, 2, 1, 3, 6]
8fun listString(values: List<Int>) = values.joinToString(", ", "[", "]")9fun preorder(node: Node?, output: MutableList<Int>) { if (node == null) return; output.add(node.value); preorder(node.left, output); preorder(node.right, output) }10fun main() { val output = mutableListOf<Int>(); preorder(sampleTree(), output); println(listString(output)) }values this step[4, 2, 1, 3] → [4, 2, 1, 3, 6]output6nodeoutput ← [4, 2, 1, 3, 6, 5]
8fun listString(values: List<Int>) = values.joinToString(", ", "[", "]")9fun preorder(node: Node?, output: MutableList<Int>) { if (node == null) return; output.add(node.value); preorder(node.left, output); preorder(node.right, output) }10fun main() { val output = mutableListOf<Int>(); preorder(sampleTree(), output); println(listString(output)) }values this step[4, 2, 1, 3, 6] → [4, 2, 1, 3, 6, 5]output5nodeoutput ← [4, 2, 1, 3, 6, 5, 7]
8fun listString(values: List<Int>) = values.joinToString(", ", "[", "]")9fun preorder(node: Node?, output: MutableList<Int>) { if (node == null) return; output.add(node.value); preorder(node.left, output); preorder(node.right, output) }10fun main() { val output = mutableListOf<Int>(); preorder(sampleTree(), output); println(listString(output)) }values this step[4, 2, 1, 3, 6, 5] → [4, 2, 1, 3, 6, 5, 7]output7nodefun main() { val output = mutableListOf<Int>(); preorder(sampleTree(),…
9fun preorder(node: Node?, output: MutableList<Int>) { if (node == null) return; output.add(node.value); preorder(node.left, output); preorder(node.right, output) }10fun main() { val output = mutableListOf<Int>(); preorder(sampleTree(), output); println(listString(output)) }values this step[4, 2, 1, 3, 6, 5, 7]output
Complexity
- Time: O(n)
- Space: O(h) recursion stack
Implementation notes
- Kotlin represents nodes with
class Node(val value: Int, var left: Node? = null, var right: Node? = null), so recursive calls must handle nullable child references. sampleTree()allocates the fixed tree with nestedNode(...)constructor calls before traversal starts.- The traversal function is
preorder(node: Node?, output: MutableList<Int>); it mutates the caller-owned output list instead of returning a new list. if (node == null) returnis the base case for missing children, so no null sentinel is added to the output.- For a real node,
output.add(node.value)happens beforepreorder(node.left, output)andpreorder(node.right, output), giving root-left-right order. maincreatesval output = mutableListOf<Int>(), callspreorder(sampleTree(), output), then formats the same list.- The trace records visits
4,2,1,3,6,5,7, with output growing from[]to[4, 2, 1, 3, 6, 5, 7]. println(listString(output))prints[4, 2, 1, 3, 6, 5, 7].