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 Bash 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.sh
Replay: real traced execution (multi-file project)
#!/usr/bin/env bash
declare -A val left right
new_node() { local id=$1 value=$2 l=${3:-0} r=${4:-0}; val[$id]=$value; left[$id]=$l; right[$id]=$r; }
render() {
  local id=$1
  if [[ "$id" == "0" || -z "$id" ]]; then printf "_"; return; fi
  if [[ "${left[$id]}" == "0" && "${right[$id]}" == "0" ]]; then printf "%s" "${val[$id]}"; return; fi
  printf "%s(" "${val[$id]}"; render "${left[$id]}"; printf ","; render "${right[$id]}"; printf ")"
}
sample_tree() {
  new_node 1 1; new_node 3 3; new_node 2 2 1 3
  new_node 5 5; new_node 7 7; new_node 6 6 5 7
  new_node 4 4 2 6
}
list_string() {
  local joined=""
  for value in "$@"; do
    [[ -n "$joined" ]] && joined+=", "
    joined+="$value"
  done
  printf '[%s]' "$joined"
}
sample_tree
output=()
preorder() { local id=$1; [[ "$id" == "0" ]] && return; output+=("${val[$id]}"); preorder "${left[$id]}"; preorder "${right[$id]}"; }
preorder 4
list_string "${output[@]}"; echo
  1. tree ← 4(2(1,3),6(5,7)), output ← []

    1#!/usr/bin/env bash2declare -A val left right
    values this step4(2(1,3),6(5,7))tree[]output
  2. output ← [4]

    24output=()25preorder() { local id=$1; [[ "$id" == "0" ]] && return; output+=("${val[$id]}"); preorder "${left[$id]}"; preorder "${right[$id]}"; }26preorder 4
    values this step[] [4]output4node
  3. output ← [4, 2]

    24output=()25preorder() { local id=$1; [[ "$id" == "0" ]] && return; output+=("${val[$id]}"); preorder "${left[$id]}"; preorder "${right[$id]}"; }26preorder 4
    values this step[4] [4, 2]output2node
  4. output ← [4, 2, 1]

    24output=()25preorder() { local id=$1; [[ "$id" == "0" ]] && return; output+=("${val[$id]}"); preorder "${left[$id]}"; preorder "${right[$id]}"; }26preorder 4
    values this step[4, 2] [4, 2, 1]output1node
  5. output ← [4, 2, 1, 3]

    24output=()25preorder() { local id=$1; [[ "$id" == "0" ]] && return; output+=("${val[$id]}"); preorder "${left[$id]}"; preorder "${right[$id]}"; }26preorder 4
    values this step[4, 2, 1] [4, 2, 1, 3]output3node
  6. output ← [4, 2, 1, 3, 6]

    24output=()25preorder() { local id=$1; [[ "$id" == "0" ]] && return; output+=("${val[$id]}"); preorder "${left[$id]}"; preorder "${right[$id]}"; }26preorder 4
    values this step[4, 2, 1, 3] [4, 2, 1, 3, 6]output6node
  7. output ← [4, 2, 1, 3, 6, 5]

    24output=()25preorder() { local id=$1; [[ "$id" == "0" ]] && return; output+=("${val[$id]}"); preorder "${left[$id]}"; preorder "${right[$id]}"; }26preorder 4
    values this step[4, 2, 1, 3, 6] [4, 2, 1, 3, 6, 5]output5node
  8. output ← [4, 2, 1, 3, 6, 5, 7]

    24output=()25preorder() { local id=$1; [[ "$id" == "0" ]] && return; output+=("${val[$id]}"); preorder "${left[$id]}"; preorder "${right[$id]}"; }26preorder 4
    values this step[4, 2, 1, 3, 6, 5] [4, 2, 1, 3, 6, 5, 7]output7node
  9. if [[ "$id" == "0" || -z "$id" ]]; then printf "_"; return; fi

    5local id=$16if [[ "$id" == "0" || -z "$id" ]]; then printf "_"; return; fi7if [[ "${left[$id]}" == "0" && "${right[$id]}" == "0" ]]; then printf "%s" "${val[$id]}"; return; fi
    values this step[4, 2, 1, 3, 6, 5, 7]output

Complexity

  • Time: O(n)
  • Space: O(h) recursion stack

Implementation notes

  • Render tree structure explicitly instead of printing node objects.
  • The replay highlights the node, traversal state, queue, path, or search cursor that changes at each step.