NivaarExam PrepOfficial exam papers ↗

25-Comp-A4 Program Design and Data Structures · December 2019

Question 7 of 9: Pointer-based Data Structures — Preorder Traversal and find_min_leaf

Nivaar worked solution (AI-drafted; not reviewed by a licensed engineer)

Notes on this paper

Paper format. 17-Comp-A4 Program Design and Data Structures, December 2019 — 3 hours, closed book, no calculator permitted. Nine questions, each of equal weight (Questions 1, 2, 7 and 8 are split 10+10; Questions 3–6 and 9 are 20 marks each), so 180 marks are printed in total. The cover page directs candidates to answer any six of the nine, and only the first six as they appear in the answer book are marked — so a complete paper is $6\times 20 = 120$ marks, which is the "total mark is out of 120" the paper's Note 6 states. Pseudocode or any high-level language (e.g. C or C++) is accepted, and the examiner's note states explicitly that marking emphasises the operation of the program, not syntactic details. All nine questions are answered below, because the whole set is the more useful revision resource. Answers are given in C or C++ as the question dictates; each is compilable as written, but a clear, correctly reasoned pseudocode answer would earn the same marks.

Reference texts for this subject.

  • Cormen, Leiserson, Rivest & Stein, Introduction to Algorithms, 4th ed. — tree walks (ch. 12), sorting and its complexity (ch. 2, 7), asymptotic analysis (ch. 3).
  • Weiss, Data Structures and Algorithm Analysis in C, 2nd ed. — arrays (ch. 1), linked lists (ch. 3), binary trees (ch. 4), searching and hashing (ch. 5).
  • Deitel & Deitel, C++ How to Program, 10th ed. — class design and operator overloading (ch. 9–11), file streams (ch. 14).
  • Kernighan & Ritchie, The C Programming Language, 2nd ed. — character/file I/O idioms (ch. 1, 7), pointers and structures (ch. 5–6).
  • Stroustrup, The C++ Programming Language, 4th ed. — value semantics, const-correctness and operator overloading (ch. 3, 11).

The Computer Engineering citation list is built around architecture and networking texts (Patterson & Hennessy, Tanenbaum, Mano); this subject is programming and data structures, so the works above are cited instead.

Question 7: Pointer-based Data Structures — Preorder Traversal and find_min_leaf (20 marks: (a) 10, (b) 10)

Question text not reproduced: the examination questions are © Engineers and Geoscientists BC. Open the official past paper (linked at the top of this page) to read the question, then follow the worked solution below.

Check: the printed struct declares left and right as struct element *, but no struct element is ever defined anywhere in this paper — it does not compile as printed. Corrected below to struct treenode *left, *right;, which is what every call site (root->left, root->right holding another TreeNode) requires.

Given. A binary tree of TreeNodes (corrected struct above), possibly empty (root == NULL).

Find. (a) A function printing every node's data in preorder (node, then left subtree, then right subtree), safe on an empty tree. (b) A function returning the smallest data value stored in a leaf (a node with no children) — not simply the smallest value anywhere in the tree.

Approach. Both are textbook structural recursions on the corrected struct: preorder visits the node itself before recursing into each child, with root == NULL as the base case that does nothing. find_min_leaf recurses into both children, but only returns a node's own value directly when that node has no children (is a leaf); an internal node's answer is the minimum of whichever child answers exist.

(a) Preorder traversal (10 marks)

  1. Write preorder() with the empty-tree base case first.
    #include <stdio.h>    /* printf(), NULL */
    
    typedef struct treenode {
        int data;
        struct treenode *left;
        struct treenode *right;
    } TreeNode;
    
    /* Preorder traversal */
    void preorder(TreeNode *root)
    {
        if (root == NULL) return;      /* empty (sub)tree: nothing to print */
        printf("%d ", root->data);
        preorder(root->left);
        preorder(root->right);
    }
  2. Trace it on a worked example tree (root 8; left child 3 with children 1 and 6, where 6 has children 4 and 7; right child 10 with right child 14, which has left child 13). Preorder visits a node, then its whole left subtree, then its whole right subtree, recursively: $$\boxed{\text{preorder} = 8,\,3,\,1,\,6,\,4,\,7,\,10,\,14,\,13}$$ and calling preorder(NULL) directly (an empty tree) prints nothing and returns immediately, as required.

(b) Smallest data value in a leaf (10 marks)

  1. Recurse, but only "count" a node when it has no children.
    #include <limits.h>
    
    int find_min_leaf(TreeNode *root)
    {
        if (root == NULL) return INT_MAX;   /* identity element for a min-fold */
    
        if (root->left == NULL && root->right == NULL)
            return root->data;              /* root itself is a leaf */
    
        int left_min  = find_min_leaf(root->left);
        int right_min = find_min_leaf(root->right);
        return (left_min < right_min) ? left_min : right_min;
    }
    A single-node tree is itself a leaf (no children), so it correctly returns its own value via the leaf base case, not the empty-tree sentinel.
  2. Trace it where the tree's global minimum is NOT a leaf — the case that actually exercises the distinction the question is testing. Take root 8 with left child 1 (an internal node with children 5 and 9) and right child 10 (a leaf). The overall smallest value in the whole tree is 1, but node "1" has two children, so it is not a leaf; the leaves are 5, 9 and 10, whose minimum is 5. $$\boxed{\text{find\_min\_leaf} = 5,\ \text{not } 1}$$ A naive "return the minimum value anywhere in the tree" implementation would wrongly report 1 here; restricting the base case to childless nodes is what makes 5 the correct answer.
Question 7 — results
PartTreeResult
(a)root 8, left 3(1,6(4,7)), right 10(—,14(13,—))preorder: 8 3 1 6 4 7 10 14 13
(a)empty tree (root = NULL)prints nothing
(b)root 8, left 1(5,9), right 10 (leaf)find_min_leaf = 5 (global min 1 is internal, excluded)