انتقل إلى المحتوى
أمين أبوزيد
منشورBEG-042-L01

الأشجار ومصطلحاتها

  • الدرس 1 من 6
  • 12 دقيقة قراءة
  • مبتدئ
في هذا الدرس 11 موضوعات

هذا الدرس متاح حاليًا باللغة الإنجليزية فقط، ولم تُنشر نسخته العربية بعد.

Lesson Overview

So far the data structures in this course have been lines: arrays, lists, stacks, and queues. Each item has a place in a row. Many things in the real world are not rows. A company has a CEO, managers under the CEO, and staff under each manager. A folder on your computer holds files and other folders. A family tree has parents and children. All of these are trees.

This lesson gives you the vocabulary of trees (root, parent, child, leaf, subtree, height) and shows how a tree looks in Java code. It also introduces the binary tree, where each node has at most two children, which is the shape the rest of this module builds on.

Why this matters: a backend developer meets trees constantly: folder structures, category menus, comment threads, JSON documents, and the indexes that databases use to find rows quickly. If you cannot name the parts of a tree, you cannot read the documentation for any of them.

This lesson builds on recursion (the call stack module) and on writing small classes. It needs nothing else from this module.

Learning Objectives

By the end of this lesson you will be able to:

  • Define a tree as nodes connected by links with no cycles.
  • Name and point out the root, parents, children, leaves, and subtrees of a drawn tree.
  • Compute the height of a tree, counting links, and explain why an empty tree is a special case.
  • Define a binary tree and write a Node class with left and right references.
  • Explain why trees are naturally recursive and write a recursive method that visits every node.
  • Tell a tree from a structure that is not a tree (one with a cycle).

Written Explanation

What a tree is

A tree is a set of nodes joined by links (also called edges). Two rules define it:

  1. There is exactly one starting node, the root, and every other node can be reached from it by exactly one path.
  2. There are no cycles: you can never follow links and arrive back where you started.

An organization chart is the classic picture. The CEO is the root. Each person has one boss (their parent) and may have people reporting to them (their children).

Trees are usually drawn upside down, with the root at the top and the branches growing downward. That is only a drawing convention.

The vocabulary

TermMeaning
RootThe top node. It has no parent.
ParentA node that has nodes directly below it.
ChildA node directly below another node, joined by one link.
SiblingsNodes that share the same parent.
LeafA node with no children.
Internal nodeA node that is not a leaf.
SubtreeAny node together with everything below it.
HeightThe number of links on the longest path from the root down to a leaf.

Take this tree. The numbers are just labels inside the nodes.

text
        8
       / \
      3   10
     / \
    1   6
  • The root is 8.
  • 3 is the parent of 1 and 6; 1 and 6 are siblings.
  • The leaves are 1, 6, and 10. The internal nodes are 8 and 3.
  • The subtree rooted at 3 is the node 3 with 1 and 6 below it.
  • The longest path is 8 to 3 to 1 (two links), so the height is 2.

Height counts links, not nodes. A tree with one node has height 0. Some books count nodes instead, so check which convention is in use. In this module, height means links.

Binary trees

A tree can have any number of children per node. A binary tree limits each node to at most two children, called the left child and the right child. Each side may also be empty. The drawing above is a binary tree.

In Java, a binary tree node needs a value and two references:

java
public class Node {
    int value;
    Node left;
    Node right;

    Node(int value) {
        this.value = value;
    }

    boolean isLeaf() {
        return left == null && right == null;
    }
}

A missing child is stored as null. A node is a leaf when both references are null. A reference to a whole tree is just a reference to its root node, and null stands for the empty tree.

Trees are recursive

Look again at the node 3 in the drawing: it is itself the root of a smaller tree. Every node is the root of its own subtree, and each subtree has the same shape as the whole. A binary tree is either empty, or a root with a left subtree and a right subtree, each of which is again a binary tree.

This is the same self-similar idea you used in recursion: solve the problem for the whole tree by solving it for the two subtrees, then combine the answers. The base case is the empty tree (null). Here is the height:

java
static int height(Node n) {
    if (n == null) return -1;
    return 1 + Math.max(height(n.left), height(n.right));
}

The base case returns -1 so that a single node, whose two children are null, gets 1 + max(-1, -1) = 0. This matches the counting-links convention. Most tree methods you will write look like this: if the node is null, return a base answer; otherwise combine the answers from the left and right subtrees.

Not every structure is a tree

If a node can be reached by two different paths, or a link leads back up to an ancestor, the structure is a graph, not a tree. A road map is a graph. Graphs get their own module later in the course.

Examples

Example 1: reading a tree by hand (simple)

Using the tree above, answer four questions:

  1. Which node is the parent of 6? Node 3.
  2. How many children does 10 have? None, so it is a leaf.
  3. Is 8 a leaf? No. It has two children.
  4. What is the height of the subtree rooted at 3? One, because the longest path from 3 goes down one link (to 1 or to 6).

Notice that the height of a subtree depends on which node you call the root. The whole tree has height 2, and the subtree at 3 has height 1.

Example 2: an org chart with more than two children (practical)

A binary tree is a special case. An org chart can give a manager three reports, so a Node with left and right is not enough. A general tree stores a list of children.

java
import java.util.ArrayList;
import java.util.List;

public class Org {
    static class Person {
        String name;
        List<Person> reports = new ArrayList<>();
        Person(String name) { this.name = name; }
    }

    static int height(Person p) {
        int best = 0;
        for (Person r : p.reports) {
            best = Math.max(best, 1 + height(r));
        }
        return best;
    }

    static void print(Person p, int depth) {
        System.out.println("  ".repeat(depth) + p.name);
        for (Person r : p.reports) print(r, depth + 1);
    }

    public static void main(String[] args) {
        Person ceo = new Person("Dana (CEO)");
        Person cto = new Person("Omar (CTO)");
        Person cfo = new Person("Lina (CFO)");
        ceo.reports.add(cto);
        ceo.reports.add(cfo);
        cto.reports.add(new Person("Sam"));
        cto.reports.add(new Person("Noor"));
        cto.reports.add(new Person("Yusuf"));
        print(ceo, 0);
        System.out.println("height = " + height(ceo));
    }
}

Output (compiled and run with JDK 21):

text
Dana (CEO)
  Omar (CTO)
    Sam
    Noor
    Yusuf
  Lina (CFO)
height = 2

A person with no reports is a leaf, and the for loop simply does nothing, so the recursion stops without a null check. From here on we use binary trees, because the two-child rule keeps the algorithms simple.

Example 3: measuring a binary tree in code (realistic)

We build the tree from the drawing by hand and measure it with three recursive methods in a Demo class that uses the Node class shown earlier.

java
public class Demo {
    static int height(Node n) {
        if (n == null) return -1;
        return 1 + Math.max(height(n.left), height(n.right));
    }

    static int size(Node n) {
        if (n == null) return 0;
        return 1 + size(n.left) + size(n.right);
    }

    static int countLeaves(Node n) {
        if (n == null) return 0;
        if (n.isLeaf()) return 1;
        return countLeaves(n.left) + countLeaves(n.right);
    }

    public static void main(String[] args) {
        Node root = new Node(8);
        root.left = new Node(3);
        root.right = new Node(10);
        root.left.left = new Node(1);
        root.left.right = new Node(6);

        System.out.println("size   = " + size(root));
        System.out.println("height = " + height(root));
        System.out.println("leaves = " + countLeaves(root));
        System.out.println("height of node 3  = " + height(root.left));
        System.out.println("is 10 a leaf? " + root.right.isLeaf());
    }
}

Output (compiled and run with JDK 21):

text
size   = 5
height = 2
leaves = 3
height of node 3  = 1
is 10 a leaf? true

All three methods follow the same pattern: handle null first, then combine the results from n.left and n.right. Each of them visits every node exactly once, so each takes time proportional to the number of nodes.

Backend Insight

Trees appear all over backend work, usually without being called trees:

  • File systems and URLs. Folders contain folders. A path such as /orders/2024/march walks down a tree.
  • JSON and XML documents. An object contains objects and arrays that contain objects. When a service parses a request body, it builds a tree in memory.
  • Categories and comments. A product category with subcategories, or a comment thread with replies, is stored as a tree in a database table in which each row points to its parent.
  • Database indexes. A database finds a row by key without reading every row by walking down a tree built for the purpose. A later module (MID-012) looks at the B-tree, which is a tree with many children per node.

The recursive habit from this lesson is how code processes all of these: handle one node and delegate the rest to its children. It carries one risk: very deep trees mean deep recursion, and every call uses a stack frame. Lesson 4 returns to this.

Common Mistakes

Mistake 1: Forgetting the null check

java
static int size(Node n) {
    return 1 + size(n.left) + size(n.right);   // wrong: no base case
}

Every leaf has null children, so the recursion eventually calls size(null) and reads n.left on null. That throws a NullPointerException. Always write if (n == null) first.

Mistake 2: Mixing up height and number of nodes

The tree in this lesson has 5 nodes and height 2. Height measures the longest path, not the count. A tree with 1,000 nodes can have a height of 9 or a height of 999, depending on its shape. That difference is the whole subject of Lesson 4.

Mistake 3: Counting nodes instead of links for height

A single node has height 0, not 1 (in this course). If you return 0 for null in height, a single node gets height 1 and every answer is off by one. Choose one convention and keep it.

Exercises

Try each exercise yourself before opening the solutions.

Use this tree for A1 to A3 and for B1: root 20 with children 12 and 30; node 12 has children 5 and 15; node 30 has only a right child, 40.

Level A: Foundation

A1. Name the root, the leaves, and the parent of 15.

أظهر الحل A1

A1. The root is 20. The leaves are 5, 15, and 40. The parent of 15 is 12.

A2. What is the height of the tree, and what is the height of the subtree rooted at 30?

أظهر الحل A2

A2. The longest path is 20 to 12 to 5 (or to 15), which is 2 links, so the height is 2. The subtree rooted at 30 has the path 30 to 40, so its height is 1.

A3. What is the largest number of nodes a binary tree of height 2 can have?

أظهر الحل A3

A3. 7 nodes: one root, two children, and four grandchildren (1 + 2 + 4).

Level B: Application

B1. Assume the Node class from this lesson and root refers to the tree above. Write the Java statements that build it.

أظهر الحل B1

B1.

java
Node root = new Node(20);
root.left = new Node(12);
root.right = new Node(30);
root.left.left = new Node(5);
root.left.right = new Node(15);
root.right.right = new Node(40);

B2. Write static int sumValues(Node n) that returns the sum of all values in a binary tree. What does it return for an empty tree?

أظهر الحل B2

B2.

java
static int sumValues(Node n) {
    if (n == null) return 0;
    return n.value + sumValues(n.left) + sumValues(n.right);
}

An empty tree returns 0, the neutral value for addition. For the tree above, the result is 122 (compiled and run with JDK 21).

B3. A file system has a folder docs that holds a.txt and a folder old; old holds b.txt. Draw it as a tree. Which items are leaves? Is docs a leaf?

أظهر الحل B3

B3. docs is the root. Its children are a.txt and old. old has one child, b.txt. The leaves are a.txt and b.txt. docs is not a leaf because it has children, and neither is old, because it holds b.txt. (An empty folder would be a leaf.)

Level C: Challenge

C1. Write static int maxValue(Node n) that returns the largest value in a binary tree (the values are not sorted). Choose a sensible result for an empty tree and explain your choice.

أظهر الحل C1

C1.

java
static int maxValue(Node n) {
    if (n == null) return Integer.MIN_VALUE;
    return Math.max(n.value, Math.max(maxValue(n.left), maxValue(n.right)));
}

Integer.MIN_VALUE is a safe answer for an empty tree because any real value is greater than or equal to it, so it never wins the max. For the tree above, the result is 40.

C2. A binary tree has 15 nodes. What is the smallest height it can have, and what is the largest? Explain in one or two sentences.

أظهر الحل C2

C2. The smallest height is 3: heights 0, 1, 2 hold at most 1, 3, and 7 nodes in total, which is fewer than 15, while height 3 allows up to 15. The largest height is 14: if every node has just one child, the tree is a chain of 15 nodes with 14 links.

Mini Challenge

Choose a tree you already know: a folder on your computer, a family, a menu on a website, or the org chart of a team. Write it down as an indented list, as the print method in Example 2 does. Then answer:

  1. Which node is the root, and which nodes are leaves?
  2. What is its height, counting links?
  3. Is it a binary tree? If not, what is the largest number of children any node has?

Check your work: the root has no parent, every other node has exactly one, and no node appears twice.

Summary & Next Lesson

Key takeaways

  • A tree is nodes joined by links with one root, one path to every node, and no cycles.
  • The vocabulary: root, parent, child, sibling, leaf, subtree, height.
  • Height counts the links on the longest root-to-leaf path. A single node has height 0 and the empty tree is -1 in our code.
  • A binary tree gives every node at most two children, left and right, with null for a missing child.
  • Trees are recursive: handle null, then combine the answers from the two subtrees.

Next lesson

The next lesson, "Binary search trees", adds one ordering rule to a binary tree: smaller values go left and larger values go right. That rule lets you search by throwing away half of the remaining tree at every step.

Self-check

  1. What are the two rules that make a structure a tree?
  2. In a binary tree, how many children can a node have at most?
  3. What is the height of a tree that has only a root node?
  4. What should a recursive tree method return or do when it receives null?
  5. A node can be reached by two different paths. Is the structure a tree?
أظهر الإجابات
  1. One root with exactly one path to every other node, and no cycles.
  2. Two: a left child and a right child.
  3. 0, when height counts links.
  4. It should return a base answer (0 for a count, -1 for height in our convention) and stop recursing, so it never reads a field of null.
  5. No. Two paths mean it has a shared node or a cycle, which makes it a graph.

References

  • NIST Dictionary of Algorithms and Data Structures: binary tree. It defines a binary tree as a tree where each node has at most two children, and as either empty or a root with a left and a right binary tree.
  • OpenDSA (Virginia Tech): Binary Tree Implementations. It shows nodes with left and right child references and a leaf defined as a node with both null. It does not give formal definitions of root, height, or subtree, so those definitions here are the common textbook ones; the course counts height in links, and other books count nodes.
  • Every Java example above was compiled and run with JDK 21 and the output is copied from the real run.

التطبيق

طبّق هذا الدرس بمختبر الوحدة وتمارينها واختبارها.

المختبر والتمارين الاختبار

تعليم الدرس كمكتمل اختياري ويمكنك التراجع عنه في أي وقت. يبقى تقدمك محفوظًا في هذا المتصفح.

اكتب للبحث في المستويات والمراحل والوحدات والدروس.