CSC 103 Lecture Notes Week 4
More on Trees, Particularly Traversal



  1. Here's a nice and simple recursive preorder traversal:
    public String traversePreorder(BinaryTreeNode t) {
        if (t == null) return "";
        return t.value.toString() + " " +
            traversePreorder(t.left) +
            traversePreorder(t.right);
    }
    

  2. Attempting traversal with a doubly-nested loop:
    public String traverseWithNestedLoop() {
    
        String result = "";                 // Return result
        BinaryTreeNode nodeI, nodeJ;        // Traversal nodes
    
        /*
         * Traverse the tree with an outer loop that visits to the left and an
         * inner loop that visits to the right.
         */
        for (nodeI = root; nodeI != null; nodeI = nodeI.left) {
            for (nodeJ = nodeI; nodeJ != null; nodeJ = nodeJ.right) {
                result = result + nodeJ.value.toString() + " ";
            }
        }
    
        return result;
    }
    

  3. Preorder traversal with an explicit stack.
    public String traverseWithStack() {
        String result = "";                 // Return result
        BinaryTreeNode current;             // Current node of traversal
        boolean done = false;               // Termination condition
    
        /*
         * Start the traversal at the root of the tree.
         */
        current = root;
    
    
        /*
         * Traverse the tree by going off to the left, while saving right
         * subtrees on a stack.  The stack gets checked when we run off the
         * left end.  The traversal continues while there are left nodes to
         * visit, and the right-node stack is not empty.
         */
        while (!done) {
            /*
             * If the current node being visited is not null, visit its value
             * by concatenating it onto the output result.  Push the right
             * subtree onto the stack, thereby saving it until we're done going
             * left.  Then make current the left subtree and continue the
             * traversal.
             */
            if (current != null) {
                result = result + current.value.toString() + " ";
                push(current.right);
                current = current.left;
            }
    
            /*
             * If the current node is null, then check the stack of postponed
             * right subtrees.  If the stack is empty, we're done with the
             * traversal.  Otherwise, pop the stack into the current node and
             * continue the traversal.
             */
            else {
                if (emptyStack()) {
                    done = true;
                }
                else {
                    current = pop();
                }
            }
        }
    
        return result;
    
    }
    

  4. Tree sizes, and observations about traversals.
    1. How many nodes are there in a completely full binary tree of height N?
    2. The answer is 1 + 2 + 4 + ... + 2N = 2N - 1 = O(2N).
    3. What does this say about our attempt to traverse a binary tree with a doubly nested for loop?
      1. Well, if we analyze the loop in terms of how many times the loop body is executed, we know that it's M2, where M is the length of an individual loop.
      2. In a complete binary tree, M is the height of the tree, since we go all the way to the left or right in any pass of a loop.
      3. This means that we can only cover O(M2) of the total O(2M) nodes in the tree.
      4. The deal is that N2 is a polynomial function that is seriously dominated by the exponential function 2N.
      5. A loop that covers N2 nodes can never possibly visit 2N nodes of a complete binary tree.




index | lectures | labs | handouts | examples | assignments | solutions | doc | grades | help