Abstract Data Types Using OOP

ADT Binary Tree

A hierarchical structure for fast searching and ordering — every node has up to two children (left and right). The ordering rule (smaller goes left, larger goes right) keeps the tree sorted automatically, so searching throws away half the tree at every step. Covers the Node/BinaryTree classes, insert (always a leaf), find (compare and go left/right), in-order traversal (prints sorted), and the Cambridge array-of-records model (tree from a linked list of records).

29.1 Introduction: The Binary Tree ADT

You have already met the linked list, where each node points to one next node, making a straight line. A binary tree changes one thing: each node may point to two nodes — a left child and a right child. That single change turns a line into a branching shape, like a family tree drawn upside down.

The version you must know is the ordered binary tree (also called a binary search tree). It follows one rule whenever a value is added: anything smaller than a node goes into its left branch, anything larger goes into its right branch. Because the data is sorted by that rule as it is inserted, finding a value later means you can throw away half the tree at every step — which is exactly why trees are fast to search.

By the end of this page you will be able to draw a tree as values arrive, build the Node and BinaryTree classes, insert and find values, and explain why reading the tree “in order” prints everything sorted.

What this page covers
  • The binary tree ADT: describing it, building it, inserting, finding, and in-order traversal.
  • The syllabus does not require you to delete from a binary tree — only insert and find.
  • Searching theory (efficiency / Big-O) is in the algorithms chapter.
TermMeaning
rootThe single node at the very top of the tree — the entry point. Everything is reached by starting here.
nodeOne item in the tree: a data value plus a left pointer and a right pointer.
childA node hanging directly below another. Each node has up to two: a left child and a right child.
parentThe node directly above a child. The root has no parent.
leafA node with no children — both its pointers are null. Leaves are the "ends" of the tree.
subtreeAny node together with everything hanging below it. A tree is made of smaller trees — which is why recursion fits so well.
ordered (BST)The rule that smaller values go left and larger values go right, keeping the data sorted as it is inserted.
in-order traversalVisiting left subtree, then the node, then right subtree. On an ordered tree this gives the data in sorted order.

29.2 Root, Children, Leaves & the Ordering Rule

Why are we doing this?
  • Cambridge often shows a tree diagram and asks you to label the root, a leaf, or to add values in the correct positions.
  • If you can read and draw the shape confidently, the coding later is just writing down what you can already see.

Picture the tree below. Mehrin enters these student marks one at a time into the revision tracker: 50, 30, 70, 20, 40, 60. The first value, 50, becomes the root. After that, every new value starts at the root and turns left (smaller) or right (larger) until it finds an empty spot, where it settles as a new leaf.

Ordered binary tree after inserting 50, 30, 70, 20, 40, 60

50
root
30
70
20
40
60
leafleafleaf
root internal nodes leavesleft < parentright > parent
Key rule
  • Start at the root for every insertion or search.
  • At each node: if your value is smaller, go left; if it is larger, go right.
  • Stop when you reach an empty (null) branch.
Exam tip:
  • When asked to “complete the diagram” by adding values, write each value's path lightly first (L / R at each node).
  • Examiners award the mark for the correct final position, so a wrong turn early loses the mark even if the rest looks neat.

29.3 The Node and BinaryTree Classes

Why are we doing this?
  • The cleanest Python model gives each Node two references — left and right — that point at other Node objects or at None.
  • This is the version you will run, and it makes insert and search short because each subtree is just another tree.
class Node:
    def __init__(self, data):
        self.data  = data       # the value stored
        self.left  = None       # left child (smaller)
        self.right = None       # right child (larger)

class BinaryTree:
    def __init__(self):
        self.root = None        # empty tree

    def insert(self, value):
        if self.root is None:
            self.root = Node(value)          # first value becomes the root
        else:
            self._insert(self.root, value)

    def _insert(self, current, value):
        if value < current.data:              # smaller -> go left
            if current.left is None:
                current.left = Node(value)
            else:
                self._insert(current.left, value)
        else:                                 # larger (or equal) -> go right
            if current.right is None:
                current.right = Node(value)
            else:
                self._insert(current.right, value)

Read the _insert method as a sentence: “if the value is smaller than this node, deal with the left side; otherwise deal with the right side.” Each time, if the branch is empty (None) we drop the new node there; if not, we ask the same question one node further down. That “ask the same question further down” is recursion.

Key rule
  • Every new value always becomes a leaf.
  • Insertion never rearranges existing nodes — it only follows left/right turns until it meets an empty branch.

29.4 Inserting a Value

Why are we doing this?
  • Mark scheme: “Add a new item to the tree” is a classic Paper 3 / Paper 4 task (e.g. the binary-tree ADT in 9618/32 specimen Q7).
  • The marks go to the correct comparison and the correct pointer being set, so tracing carefully is the whole skill.

Tracing an insert means walking from the root and writing down each decision. Below, Aymaan inserts 45 into the tree from Section 2.

Task — Worked Example — Insert 45
Insert 45 into the tree 50, 30, 70, 20, 40, 60.
Hint:
  • Start at the root. At each node: smaller go left, larger go right. Stop at an empty branch.
Your Turn — Your Turn — Insert 65
Insert 65 into the same tree. Write each decision, then state whose child 65 becomes.
Hint:
  • Start at the root every time, and remember larger goes right.

29.5 Finding a Value

Why are we doing this?
  • Searching a binary tree reuses the exact same left/right logic as insertion — but instead of dropping a node, you report found / not found.
  • The syllabus specifically asks you to “write an algorithm to find an item in a binary tree.”
def find(self, target):
    current = self.root
    while current is not None:
        if target == current.data:
            return True                    # found it
        elif target < current.data:
            current = current.left         # smaller -> left subtree
        else:
            current = current.right        # larger -> right subtree
    return False                           # fell off the tree -> not present

Each comparison lets you ignore an entire subtree, so on a well-shaped tree you check far fewer than every node. The loop ends two ways: a match (True), or running off the bottom into None (False).

Task — Worked Example — Find 60
Find 60 in 50, 30, 70, 20, 40, 60.
Hint:
  • Start at the root; compare; go left or right; stop on match or None.
Your Turn — Your Turn — Find 35
Find 35 in the same tree. What does find return, and how many nodes are visited?
Hint:
  • The loop stops when current becomes None.
Exam tip:
  • If a tree is built from data that arrives already sorted, it degrades into a single long branch — effectively a linked list — and search is no faster than checking every item.
  • Mentioning this trade-off earns the higher-level mark in “evaluate” questions.

29.6 In-Order Traversal (Reading It Sorted)

Why are we doing this?
  • “Traverse the tree” appears repeatedly in the specimen and past papers.
  • The most useful traversal is in-order, because on an ordered tree it always outputs the data in ascending order — a neat way to sort.

In-order means: for any node, first deal with its left subtree, then visit the node itself, then its right subtree. Because left always holds smaller values, you naturally print from smallest to largest.

def in_order(self, node):
    if node is not None:
        self.in_order(node.left)        # 1. left subtree
        print(node.data, end=" ")       # 2. this node
        self.in_order(node.right)       # 3. right subtree

# In-order traversal of 50, 30, 70, 20, 40, 60 produces:
# 20 30 40 50 60 70  -- sorted ascending!
Task — Worked Example — In-order of 50, 30, 70, 20, 40, 60
Give the in-order output of the tree 50, 30, 70, 20, 40, 60.
Hint:
  • Left subtree of 50 first → 30-subtree gives 20, 30, 40. Then 50. Then right subtree → 60, 70.
Your Turn — Your Turn — In-order of 15, 8, 25, 4, 12
Nazifa inserts 15, 8, 25, 4, 12. Give the in-order output.
Hint:
  • You don't need to draw it; in-order on an ordered tree is just the values sorted.

29.7 The Array-of-Records Model (ADT from Another ADT)

Why are we doing this?
  • Mark scheme: Cambridge often asks you to implement a tree without object references — as a 1D array of records, each with a left pointer and a right pointer holding array indices (see 9618/03 specimen Q7).
  • This shows a tree built from a linked list of records — one ADT from another.

Each node is a record: Data, LeftPointer, RightPointer. A RootPointer stores the index of the root; a FreePointer tracks the next unused slot. The null pointer is -1 (or 0 if the array starts at 1). Below is the tree 50, 30, 70 stored this way.

IndexDataLeftPointerRightPointerrole
05012root
130-1-1leaf
270-1-1leaf

RootPointer = 0. Node 0 (the root, 50) points left to index 1 (30) and right to index 2 (70). Both 30 and 70 are leaves (their pointers are -1).

Key rule — one ADT from another
  • A binary tree is built from a linked list of records: each record (node) is linked to others by index pointers, exactly like a linked list, but with two pointers instead of one.
  • This is the “implement an ADT from another ADT” point examiners look for.

29.8 Full Exam-Style Question

Paper 3 / Paper 4 · binary tree · ~13 marks
  • moshikur.com stores unique student ID numbers in an ordered binary tree so they can be searched quickly.
  • Each Node record has fields Data, LeftPointer and RightPointer.
  • RootPointer indexes the root and the null pointer is -1.

(a) [2] Describe two features of a binary tree ADT. (AO1)

(b) [3] The IDs 500, 300, 800, 200, 400 are inserted in that order. Draw the resulting ordered binary tree. (AO2)

(c) [4] Complete the function FindID(Target) that returns the index of the node holding Target, or -1 if absent. (AO2)

FUNCTION FindID(Target) RETURNS INTEGER
    ThisPtr <- ....................
    WHILE ThisPtr <> -1
        IF Tree[ThisPtr].Data = Target THEN
            RETURN ....................
        ELSEIF Target < Tree[ThisPtr].Data THEN
            ThisPtr <- ....................
        ELSE
            ThisPtr <- ....................
        ENDIF
    ENDWHILE
    RETURN -1
ENDFUNCTION

(d) [2] State the output of an in-order traversal of the tree in part (b), and explain why it is in this order. (AO2)

(e) [2] Explain one disadvantage of a binary tree if the IDs happen to be inserted in ascending order. (AO3)

Lab Task — Show mark scheme
Reveal the mark scheme for parts (a)–(e).
Hint:
  • (a) 2 from: node = data + two pointers; one root; ordered smaller-left/larger-right; leaves null; hierarchical.
  • (b) 500 root; 300 left, 800 right; 200 left of 300; 400 right of 300.
  • (c) ThisPtr ← RootPointer; RETURN ThisPtr; ThisPtr ← Tree[ThisPtr].LeftPointer; ThisPtr ← Tree[ThisPtr].RightPointer.
  • (d) 200 300 400 500 800; in-order visits left (smaller) then node then right (larger) = ascending.
  • (e) tree becomes one long branch (like a linked list); search no faster than checking every node.

Key Points Summary

A binary tree gives every node up to two children — a left child and a right child. That turns a linked list's line into a branching shape.
The ordered binary tree (BST) rule: smaller values go left, larger values go right. This keeps the data sorted as it is inserted, so searching is fast.
The root is the single node at the top — the entry point. The first value inserted becomes the root.
A leaf is a node with no children — both its pointers are null. Leaves are the "ends" of the tree.
Each node holds data plus a left pointer and a right pointer. A parent is the node directly above a child; the root has no parent.
Start at the root for every insertion or search. At each node: smaller go left, larger go right. Stop when you reach an empty (null) branch.
Every new value always becomes a leaf. Insertion never rearranges existing nodes — it only follows left/right turns until it meets an empty branch.
The Node class has three fields: data, left (smaller), right (larger). The BinaryTree class has root (None for empty).
Insert uses recursion: if the branch is empty (None) drop the new node there; otherwise ask the same question one node further down.
find: start at the root, loop while current is not None. If target == data return True; if target < data go left; else go right. Return False if you fall off the tree.
Each comparison in find lets you ignore an entire subtree — on a well-shaped tree you check far fewer than every node.
In-order traversal: visit left subtree, then the node, then right subtree. On an ordered tree this gives the data in ascending (sorted) order.
In-order traversal is recursive: in_order(node.left), then print node.data, then in_order(node.right).
The Cambridge array model: each node is a record with Data, LeftPointer, RightPointer (array indices). RootPointer indexes the root; null is -1 (or 0).
A binary tree built from a linked list of records (two pointers per node) is an example of implementing an ADT from another ADT.
If data arrives already sorted, the tree degrades into a single long branch (like a linked list) and search is no faster than checking every item — mention this trade-off in "evaluate" questions.

29.9 Practice Tasks

Fifteen exam-style tasks. Click Hint for bullet-point guidance, then Help to reveal a worked Python/pseudocode solution.

1Practice Task — Describe a binary tree [2 marks]
Describe two features of a binary tree ADT.
2Practice Task — Node and BinaryTree classes [6 marks]
Write a Node class (data, left, right) and a BinaryTree class with __init__ (root=None) and insert (recursive _insert with smaller-left/larger-right).
3Practice Task — find method [4 marks]
Write a find(self, target) method that returns True if target is in the tree, False otherwise.
4Practice Task — in_order method [4 marks]
Write an in_order(self, node) method that prints the tree in-order (left, node, right).
5Practice Task — Trace insert 45 [3 marks]
Insert 45 into 50, 30, 70, 20, 40, 60. Give each decision and the final parent.
6Practice Task — Trace insert 65 [3 marks]
Insert 65 into the same tree. Whose child does 65 become?
7Practice Task — Trace find 60 [2 marks]
Find 60 in 50, 30, 70, 20, 40, 60. How many nodes are visited?
8Practice Task — Trace find 35 [2 marks]
Find 35 in the same tree. What does find return, and how many nodes are visited?
9Practice Task — In-order output [2 marks]
Give the in-order output of 50, 30, 70, 20, 40, 60.
10Practice Task — In-order of 15, 8, 25, 4, 12 [2 marks]
Nazifa inserts 15, 8, 25, 4, 12. Give the in-order output.
11Practice Task — Draw a tree [3 marks]
Insert 500, 300, 800, 200, 400 in that order. Describe the resulting tree (who is root, left/right children).
12Practice Task — Pseudocode FindID [4 marks]
Write Cambridge pseudocode for FUNCTION FindID(Target) RETURNS INTEGER using RootPointer, LeftPointer, RightPointer, null = -1.
13Practice Task — Array model table [3 marks]
Given RootPointer=0, Index 0: Data=50/Left=1/Right=2, Index 1: Data=30/Left=-1/Right=-1, Index 2: Data=70/Left=-1/Right=-1. What is the RightPointer of the root? Is node 1 a leaf?
14Practice Task — Disadvantage of sorted input [2 marks]
Explain one disadvantage of a binary tree if the IDs happen to be inserted in ascending order.
15Practice Task — Full exam-style: student ID tree [13 marks]
Student IDs stored in an ordered binary tree (Node: Data, LeftPointer, RightPointer; RootPointer; null = -1). (a) Describe 2 features [2]. (b) Insert 500,300,800,200,400 — draw tree [3]. (c) Complete FindID(Target) [4]. (d) In-order output + why [2]. (e) Disadvantage of ascending insertion [2].

Question Bank

Answer all questions, then press Submit Quiz to see your score.

0/12 answered

Question 1Multiple Choice

A binary tree gives every node up to:

Question 2Multiple Choice

In an ordered binary tree (BST), where does a larger value go?

Question 3True / False

The first value inserted into a binary tree becomes the root.

Question 4Multiple Choice

What is a leaf?

Question 5Multiple Choice

In the Node class, what are the three fields?

Question 6Multiple Choice

When inserting, every new value:

Question 7Multiple Choice

In find, if target < current.data, which way do you go?

Question 8True / False

In-order traversal visits left subtree, then the node, then right subtree.

Question 9Multiple Choice

In-order traversal of an ordered binary tree outputs values in what order?

Question 10Multiple Choice

In the Cambridge array model, what does each node record have?

Question 11Multiple Choice

If data arrives already sorted, the binary tree:

Question 12Multiple Choice

A binary tree built from a linked list of records (two pointers per node) is an example of:

Answer all 12 questions to enable submission.