Trees in DSA: The Beginner’s Guide I Wish I Had

Understand trees from scratch — nodes, traversals, recursion, Binary Search Trees, Tries, and the problem-solving patterns that make everything click.

Trees in DSA: The Beginner’s Guide I Wish I Had

Trees are one of those DSA topics that look ridiculously simple at first.

You have some nodes. You connect them. Some nodes have children. Done.

Then you open a coding problem and suddenly you’re asked to find the diameter of a tree, the lowest common ancestor, construct a tree from preorder and inorder, or serialize and deserialize it.

And you’re left thinking:

How did a few circles connected by lines become this complicated?

I think part of the problem is how we usually learn Trees.

We start with words like root, leaf, height, depth, subtree, and traversal.

There are so many new terms that the actual idea gets lost.

So let’s start from zero.

The goal isn’t to memorise a list of tree algorithms.

The goal is to understand how to look at a tree.


Learning Objectives

  1. What a Tree is and why we use it

  2. Basic Tree terminology

  3. Different types of Trees

  4. Binary Trees

  5. Representing Trees in JavaScript

  6. Tree Traversals: DFS & BFS

  7. Preorder, Inorder & Postorder

  8. Level Order Traversal

  9. Recursion with Trees

  10. Common Binary Tree problems

  11. Binary Search Trees (BST)

  12. Tree Construction

  13. Tries

  14. Introduction to Advanced Trees

  15. How to approach Tree problems

  16. Common patterns to recognise in Tree questions


1. What Is a Tree?

Think about a company’s organisation chart.

  • There is a CEO at the top.

  • The CEO manages a few people.

  • Those people manage other people.

And the structure keeps branching.

That’s the basic idea of a tree.

For example:

                 CEO
               /     \
            CTO       CFO
           /   \       |
        Dev 1  Dev 2  Finance

The person at the top is connected to people below them.

In DSA, instead of people, we have nodes.

A simple tree might look like this:

        1
       / \
      2   3
     / \
    4   5

Here:

  • 1 is the root

  • 2 and 3 are children of 1

  • 4 and 5 are children of 2

  • 4, 5, and 3 are leaf nodes because they have no children

There are a few other terms you’ll see often.

Parent

A node directly above another node.
2 is the parent of 4.

Child

A node directly below another node.
4 is a child of 2.

Siblings

Nodes that have the same parent.
2 and 3 are siblings.

Ancestor

A node somewhere above another node.
For example, 1 is an ancestor of 4.

Descendant

A node somewhere below another node.
4 is a descendant of 1.
And one word that becomes very important later:

Subtree

Take any node and everything below it.
For example, the subtree rooted at 2 is:

      2
     / \
    4   5

This small idea is actually one of the biggest reasons trees work so well with recursion.

We’ll come back to it.


2. Why Do We Need Trees?

At this point you might be thinking:

Why not just use an array?

That’s a very reasonable question.

Arrays are great when your data is naturally a sequence:

10 → 20 → 30 → 40 → 50

But what if your data is hierarchical?

Consider a file system:

Documents
├── Work
│   ├── Resume.pdf
│   └── Project.docx
├── Photos
│   ├── Trip
│   └── Family
└── Personal
    └── Notes

An array doesn’t naturally represent this relationship.

A tree does.

That’s why you see tree-like structures in many places:

  • File systems

  • HTML DOM

  • Organisation hierarchies

  • Decision systems

  • Autocomplete

  • Search indexes

  • Compilers

  • Databases

The important idea is:

Trees are useful when your data naturally has a hierarchy or branching structure.

Once you start seeing hierarchical data this way, trees become much less abstract.


3. Types of Trees

There isn’t just one kind of tree.

There are several types, each designed for different situations.

You don’t need to learn all of them at once.

Think of them as a family:

Tree
│
├── Binary Tree
│
├── Binary Search Tree
│
├── Heap
│
├── Trie
│
├── AVL Tree
│
├── Red-Black Tree
│
└── Segment Tree

We’ll focus mostly on Binary Trees, because they are one of the best places to learn the fundamentals.

Once you understand Binary Trees, many of the ideas you learn will carry over to other tree structures.


4. Binary Tree

A Binary Tree is simply a tree where each node can have at most two children.

We normally call them:

left child
right child

For example:

          1
        /   \
       2     3
      / \
     4   5
  • Node 1 has two children.

  • Node 2 has two children.

  • Node 3 has no children.

  • Node 4 has no children.

There is no requirement that every node must have exactly two children.

This is perfectly valid:

       1
      /
     2
      \
       3

A node can have:

  • zero children

  • one child

  • two children

But never more than two.


5. How Do We Represent a Tree in JavaScript?

Let’s create a node.

class TreeNode {
    constructor(value) {
        this.value = value;
        this.left = null;
        this.right = null;
    }
}

Now we can create nodes:

const root = new TreeNode(1);
const node2 = new TreeNode(2);
const node3 = new TreeNode(3);

root.left = node2;
root.right = node3;

We now have:

       1
      / \
     2   3

We can continue:

node2.left = new TreeNode(4);
node2.right = new TreeNode(5);

Our tree becomes:

          1
        /   \
       2     3
      / \
     4   5

And this is the representation you’ll see again and again in JavaScript tree problems.

Usually, a problem gives you something like:

root

and your job is to work with the tree starting from that root.


6. Tree Traversals — How Do We Visit Every Node?

Now we have a tree.

But how do we actually move through it?

Suppose we want to print every value.

Which node should we visit first?

          1
        /   \
       2     3
      / \
     4   5

Do we go:

1 → 2 → 4 → 5 → 3

or:

4 → 2 → 5 → 1 → 3

or something else?

There isn’t just one correct way.

These different ways of visiting nodes are called tree traversals.

The four you should know first are:

  1. Preorder

  2. Inorder

  3. Postorder

  4. Level Order


Preorder

The rule is: Root → Left → Right

For our tree:

          1
        /   \
       2     3
      / \
     4   5

We visit:

1 → 2 → 4 → 5 → 3

Think:

Visit me first, then my left side, then my right side.


Inorder

The rule is: Left → Root → Right

So:

4 → 2 → 5 → 1 → 3

Inorder becomes especially interesting when we talk about Binary Search Trees.


Postorder

The rule is: Left → Right → Root

So:

4 → 5 → 2 → 3 → 1

Think:

Let my children finish first. Then process me.

This becomes useful in problems where you need information from the children before deciding what to do with the current node.


Level Order

Instead of going deep first, we visit the tree level by level.

          1
        /   \
       2     3
      / \
     4   5

The order becomes:

1 → 2 → 3 → 4 → 5

Usually, we implement this using a queue.

Level 1:       1
Level 2:      2  3
Level 3:     4  5

This is also called Breadth-First Search (BFS).


7. The Big Tree Insight: Recursion

This is probably the most important concept to understand.

Look at this tree:

          1
        /   \
       2     3
      / \
     4   5

Now look only at the left side:

       2
      / \
     4   5

Isn’t that also a tree? Yes.

And look at node 4.

4

That’s also a tree — just a tree with no children.

This is the key idea:

A tree is made up of smaller trees.

And that is why recursion fits trees so naturally.

Let’s say we simply want to visit every node.

function dfs(node) {
    if (node === null) {
        return;
    }
  console.log(node.value);
    dfs(node.left);
    dfs(node.right);
}

The function says:

  1. If there is no node, stop.

  2. Process the current node.

  3. Do the same thing for the left subtree.

  4. Do the same thing for the right subtree.

Notice something interesting.

We don’t tell the function:

“Go through this particular tree with 7 nodes.”

We tell it:

“Here is a node. Do the same thing for whatever is below it.”

That is recursion.


8. The Mental Model That Makes Tree Problems Easier

When you see a tree problem, don’t immediately think:

“How do I solve this entire tree?”

Instead ask:

“If I already knew the answer for the left subtree and the right subtree, how could I use those answers to solve the current node?”

This one question is extremely useful.

For example, suppose we want the maximum depth.

          1
        /   \
       2     3
      / \
     4   5

The depth of node 1 depends on:

  • depth of the left subtree

  • depth of the right subtree

So:

function maxDepth(node) {
    if (node === null) {
        return 0;
    }
    const leftDepth = maxDepth(node.left);
    const rightDepth = maxDepth(node.right);
    return 1 + Math.max(leftDepth, rightDepth);
}

The important part isn’t memorising this code.

It’s understanding the thought process:

           Current Node
             /       \
            /         \
    Left Answer     Right Answer
            \         /
             \       /
              Combine

This pattern appears in many tree problems.


9. Common Binary Tree Problems

Once you understand traversal and recursion, many beginner tree problems become variations of the same idea.

Maximum Depth

We already saw it.

Ask:

What is the maximum depth of my left and right subtrees?

Then add one for the current node.


Count the Nodes

Again:

function countNodes(node) {
    if (node === null) {
        return 0;
    }
    return 1 +
        countNodes(node.left) +
        countNodes(node.right);
}

The thinking is:

Count me + count everything on my left + count everything on my right.


Same Tree

You are given two trees.

You need to determine whether they are identical.

Instead of comparing the entire trees at once:

Are these two nodes equal?
        ↓
Are their left subtrees equal?
        ↓
Are their right subtrees equal?

Again, the same recursive thinking.


Invert a Binary Tree

Given:

        1
      / \
     2   3

Turn it into:

       1
      / \
     3   2

At every node:

swap(left, right)

and repeat for the children.

Simple idea.

But it becomes much easier once you understand that the same operation can be applied to every subtree.


Diameter of a Binary Tree

This one is a little more interesting.

The diameter is the longest path between two nodes.

You might initially think:

“How do I find every possible path?”

But recursion gives us another way to think.

At every node:

longest path through this node
=
left depth + right depth

Then we keep track of the largest value we’ve seen.

This is a good example of a tree problem where the information returned by recursion and the final answer aren’t necessarily the same thing.


10. Binary Search Tree — When the Tree Has an Order

A Binary Tree only tells us:

Each node can have at most two children.

A Binary Search Tree (BST) adds an important rule.

For every node:

left side < node < right side

For example:

          8
        /   \
       3     10
      / \      \
     1   6      14

Everything on the left of 8 is smaller than 8.

Everything on the right is greater than 8.

Now imagine searching for 14.

Start at 8.

14 > 8

So don’t bother searching the entire left subtree.

Go right.

14 > 10

Go right again.

Found it.

That’s the benefit of the ordering.

And there’s another very useful property:

Inorder traversal of a valid BST produces values in sorted order.

For our tree:

1 → 3 → 6 → 8 → 10 → 14

That connection between traversal and BST is worth remembering.


11. Tree Construction

Here’s where tree problems start feeling like puzzles.

Suppose you’re given:

Preorder:
[3, 9, 20, 15, 7]
Inorder:
[9, 3, 15, 20, 7]

Can you reconstruct the tree?

The trick is to understand what each traversal tells us.

Preorder

Root → Left → Right

So the first element tells us the root.

Here:

3

is the root.

Now look for 3 in the inorder traversal:

[9, 3, 15, 20, 7]
    ↑
   root

Everything before it belongs to the left subtree.

Everything after it belongs to the right subtree.

So:

        3
       / \
      9   20
         /  \
        15   7

The beautiful part is that the same idea repeats for the smaller subtrees.

Again:

A tree problem often becomes easier when you stop looking at the entire tree and start looking at one subtree at a time.


12. Trie — The Other Tree You Should Know

Not every tree problem is about numbers.

Sometimes we’re dealing with strings.

Suppose you have:

cat
car
can

A Trie can store these words by sharing their common prefixes.

Conceptually:

         root
          |
          c
          |
          a
        / | \
       t  r  n

The first two letters are shared.

That makes Tries useful for problems involving prefixes.

For example:

Find all words that start with "ca".

That’s exactly the kind of problem a Trie is designed to handle.

You’ll see Tries in concepts such as:

  • autocomplete

  • dictionaries

  • prefix searching

  • word lookup

You don’t need to master Tries before learning Binary Trees.

But once Binary Trees make sense, Tries become much easier to approach.


13. Advanced Trees — Just Know They Exist

Once you go deeper into DSA, you’ll encounter more specialised trees.

You don’t need to learn all of them today.

Just know what problem they are trying to solve.

Trees and their common usage

The important thing is not to memorise this table.

It’s to understand that different tree structures exist because different problems need different properties.

For now, Binary Trees are enough.


14. The Most Important Section: How to Approach Tree Problems

This is the checklist I wish someone had given me earlier.

When you see a new tree problem, don’t immediately start writing code.

Ask these questions.

1. What exactly am I being asked to find?

Is it:

  • a value?

  • a count?

  • a depth?

  • a path?

  • a boolean?

  • the actual tree?


2. Do I need to visit every node?

If yes, think:

DFS or BFS?

If the problem talks about levels, shortest distance in an unweighted tree, or something happening level by level, BFS may be useful.

Otherwise, DFS is often a natural starting point.


3. Can I solve the current node using the answers from its children?

If yes, recursion is probably worth considering.

Ask:

What should my recursive function return?

This is often the hardest and most important question.


4. Is the information moving upward or downward?

Sometimes you need information from the children:

children
   ↓
current node

That’s a common bottom-up recursion pattern.

Other times you carry information from the parent:

parent
  ↓
child
  ↓
grandchild

For example, you may need to carry the current path, depth, or remaining target.


5. What happens when the node is null?

This sounds small, but it’s one of the most important questions in recursive tree problems.

For example:

if (node === null) {
    return 0;
}

The base case tells recursion when to stop.


6. Is this a Binary Tree or a BST?

Don’t assume every binary tree is a BST.

A Binary Tree:

       10
       /  \
     100   2

is completely valid.

A BST is not, because the left side contains 100, which is greater than 10.

That ordering rule only exists in a BST.


A Simple Tree Problem-Solving Flow

When you’re stuck, try this:

             Tree Problem
                  |
                  ↓
          What is being asked?
                  |
          ┌───────┴────────┐
          ↓                ↓
       Levels?         Subtree info?
          |                |
          ↓                ↓
         BFS              DFS
                           |
                           ↓
              Can left + right answers
              help solve current node?
                           |
                    ┌──────┴──────┐
                    ↓             ↓
                   Yes            No
                    |             |
                    ↓             ↓
               Recursion      Think about
                              state/path/
                              other structure

You don’t have to follow this perfectly.

It’s simply a way to slow down before jumping into code.


So, What Should You Actually Learn?

If you’re starting Trees today, don’t try to learn everything at once.

I’d go in this order:

1. Tree terminology
        ↓
2. Binary Tree
        ↓
3. TreeNode representation
        ↓
4. DFS
        ↓
5. Preorder / Inorder / Postorder
        ↓
6. BFS / Level Order
        ↓
7. Recursion
        ↓
8. Basic tree problems
        ↓
9. Binary Search Tree
        ↓
10. Tree construction
        ↓
11. Trie
        ↓
12. Advanced trees

And don’t rush through recursion.

If recursion doesn’t feel comfortable yet, that’s okay.

Tree problems are actually a great way to get better at it.


The Mental Model I Took Away

The biggest change isn’t learning another traversal or memorising another piece of code.

It’s changing the way you look at the problem.

Earlier, a tree can look like this giant structure:

                 1
              /     \
             2       3
           /   \    / \
          4     5  6   7
         / \
        8   9

And you might think:

“How am I supposed to process all of this?”

But you can zoom in.

Look at node 2:

       2
      / \
     4   5

That’s a tree.

Look at node 4:

    4
   / \
  8   9

That’s another tree.

And eventually:

8

is a tree too.

Once you start thinking this way, recursion stops feeling like some magical trick.

You are simply saying:

“I’ll solve the smaller trees first, and then use their answers to solve the bigger tree.”

That, for me, is the real foundation of solving tree problems.

  • The syntax will change.

  • The problem will change.

  • The tree will change.

But this way of thinking keeps coming back.


From Tech By Neha Gupta

  • 👏 Enjoyed the article? Don’t forget to leave a clap.

  • 💬 Have thoughts or questions? Share them in the comments.