<style> .reveal-up, .reveal-left, .reveal-right, .reveal-stagger > * { opacity: 1 !important; transform: none !important; } </style>
  1. Learn
  2. DSA
  3. Trees
All lessons in this course

Lesson 25 of 50 13 minIntermediate

Trees and binary trees

Learn the vocabulary of trees (root, parent, child, leaf, depth, height, subtree), build a general tree in C#, and meet binary trees and why their height matters.

Arrays, lists, stacks and queues are linear: every item has at most one item before it and one after it. Much real data is not like that. A project has buildings, a building has levels, a level has columns. A folder has files and sub-folders. A web page has elements inside elements. This shape, one thing branching into several, is a tree.

The vocabulary

TermMeaning
NodeOne item in the tree (Project, Level 1, C1…)
EdgeThe link from a parent to a child
RootThe single node at the top; it has no parent
Parent / childA node directly above / directly below another
SiblingsNodes with the same parent
LeafA node with no children
SubtreeA node together with everything below it
Depth of a nodeNumber of edges from the root down to it (the root has depth 0)
Height of a nodeNumber of edges on the longest path from it down to a leaf (a leaf has height 0)
Height of the treeThe height of the root
Interactive

Anatomy of a tree

A project broken down into buildings, levels and columns. Click any node.

C1C2Level 1C3Level 2Bldg AB1B2B3Level 1Bldg BProject

Amber = selected · blue = path from the root · purple = its subtree · dashed = leaf

KindInternal node
Depth2edges from the root
Height1edge down to its deepest leaf
ParentBldg A
ChildrenC1, C2
Subtree size3nodes
Path: Project → Bldg A → Level 1. The whole tree has 12 nodes and 11 edges (always n − 1) and height 3.

Two facts hold for every tree: every node except the root has exactly one parent, and there are no loops. So a tree with n nodes always has n − 1 edges. If any node had two parents, or you could walk in a circle, it would be a graph (covered in the Graphs module).

A general tree in C#

A node stores its data and a list of children. Because each child is itself the root of a smaller tree, almost every tree algorithm is naturally recursive: handle this node, then call yourself on each child.

GeneralTree.cs
var project = new TreeNode("Project");var a = project.Add("Building A");var a1 = a.Add("Level 1");a1.Add("C1");a1.Add("C2");a.Add("Level 2").Add("C3");project.Add("Building B").Add("Level 1").Add("B1"); Print(project, 0);Console.WriteLine($"Nodes: {Count(project)}, height: {Height(project)}"); static void Print(TreeNode node, int depth){    Console.WriteLine(new string(' ', depth * 2) + node.Name);   // indent by depth    foreach (var child in node.Children)        Print(child, depth + 1);} static int Count(TreeNode node) => 1 + node.Children.Sum(c => Count(c)); static int Height(TreeNode node) =>    node.Children.Count == 0 ? 0 : 1 + node.Children.Max(c => Height(c)); class TreeNode{    public string Name { get; }    public List<TreeNode> Children { get; } = new();    public TreeNode(string name) => Name = name;     public TreeNode Add(string name)    {        var child = new TreeNode(name);        Children.Add(child);        return child;                       // so calls can be chained    }}
Output
Project
  Building A
    Level 1
      C1
      C2
    Level 2
      C3
  Building B
    Level 1
      B1
Nodes: 10, height: 3

You use trees like this every day: System.IO.Directory (folders), XML and JSON documents (XElement, JsonNode), the HTML DOM, menus, an organisation chart, and Revit or Tekla model hierarchies.

Binary trees

In a binary tree every node has at most two children, called left and right. The order matters: a node with only a left child is different from one with only a right child. Binary trees are the base of binary search trees, heaps and expression trees in the next lessons.

BinaryNode.cs
//        8//      /   \//     4     12//    / \//   2   6var root = new Node(8,    new Node(4, new Node(2), new Node(6)),    new Node(12)); Console.WriteLine(root.Left!.Right!.Value);   // 8 → left → right record Node(int Value, Node? Left = null, Node? Right = null);
Output
6

Why height is the number to watch

Most tree operations walk from the root down one path, so they cost O(height). How tall a binary tree with n nodes is depends entirely on its shape:

  • Perfect / complete (every level full, or full except the last, filled from the left): height ≈ log₂ n. A million nodes fit in about 20 levels.
  • Degenerate (every node has one child): it is really a linked list, height n − 1. Walking it is O(n).
Height hMost nodes a binary tree can hold (2ʰ⁺¹ − 1)
01
315
91,023
191,048,575
29about 1 billion

Keeping trees short (“balanced”) is what makes them fast. The whole Trees module is about that idea.

Quick check

A tree has 25 nodes. How many edges does it have?

Quick check

In the Project tree printed above, what is the depth of C3 and the height of Building A?

Practice

Using the TreeNode class above, write Leaves(TreeNode node) that counts the leaves, and Find(TreeNode node, string name) that returns the first node with that name (or null), searching depth first. For the Project tree: 4 leaves, and Find(project, "C3") returns the node named C3.

Show a hint

A leaf counts 1; any other node is the sum over its children. For Find, check the node itself, then search each child and return the first non-null result.

Show the solution
Solution.cs
var project = new TreeNode("Project");var a = project.Add("Building A");var a1 = a.Add("Level 1");a1.Add("C1");a1.Add("C2");a.Add("Level 2").Add("C3");project.Add("Building B").Add("Level 1").Add("B1"); Console.WriteLine(Leaves(project));Console.WriteLine(Find(project, "C3")?.Name ?? "not found");Console.WriteLine(Find(project, "C9")?.Name ?? "not found"); static int Leaves(TreeNode node) =>    node.Children.Count == 0 ? 1 : node.Children.Sum(c => Leaves(c)); static TreeNode? Find(TreeNode node, string name){    if (node.Name == name) return node;    foreach (var child in node.Children)    {        var hit = Find(child, name);        if (hit is not null) return hit;    }    return null;} class TreeNode{    public string Name { get; }    public List<TreeNode> Children { get; } = new();    public TreeNode(string name) => Name = name;    public TreeNode Add(string name) { var c = new TreeNode(name); Children.Add(c); return c; }}
Output
4
C3
not found

Remember

  • A tree is a hierarchy: one root, every other node has exactly one parent, no loops, n − 1 edges.
  • Depth counts edges from the root; height counts edges down to the deepest leaf.
  • Tree code is naturally recursive: do the node, then recurse into the children.
  • Operations cost O(height): about log₂ n for a balanced binary tree, n for a degenerate one.
0 of 50 lessons completed