CS 2005, B Term 1999
Data Structures and Programming Techniques
Test 2 Solutions

Your Name: _____________________________________

Your Lab Section: ______________     Your Login Name:_________________

Instructions.   Read each problem carefully before answering. Circle the selected answer(s) or write your solutions in ink in the spaces provided when this is the appropriate action as indicated below for each problem. Write neatly. Each problem is worth 60 points. All parts of each problem have equal point value. Good luck!

  1. Assume the following definition of the Node type:
    
       struct Node {
          typedef ___ Item;
          Item data;
          Node* link;
       };
    
    
    a) Fill in the blanks in the for statement below so that the resulting program segment leaves the correct length of the linked list with head pointer head_ptr in the variable named length.
    
       Node* cursor;
       size_t length = 0;
       for (cursor = head_ptr; cursor != NULL; cursor = cursor->link)
          length++;
    
    

    b) Write the output produced by the following program segment next to the word "Answer" below, or write "SEGMENTATION FAULT" if the program attempts to access unallocated memory (but show all partial output produced before any such illegal access). Assume that the constructor for the Item type initializes all Item objects as 0.

    
       Node *head_ptr, *cursor;
       head_ptr = new Node;
       head_ptr->data = 5;
       head_ptr->link = new Node;
       cursor = head_ptr;
       cout << cursor->data << endl;
    
       Answer: 5
    
    

    c) As in b), but for the following program segment. Assume that Item is size_t in this context.

    
       Node *head_ptr, *cursor;
       head_ptr = new Node;
       cursor = head_ptr;
       for (size_t i=0; i<10; i++) {
          cursor->data = i;
          cursor->link = new Node;
          cursor = cursor->link;
       }
       for (size_t i=0; i<10; i++) {
          cout << cursor->data << endl;
          cursor = cursor->link;
       }
    
       Answer: 0 
               SEGMENTATION FAULT
    
    
    
    
    
    
    
    
    

  2. For each of the following binary trees, circle all of the attributes that apply to it. For example, if the tree is a balanced binary search tree, then both "balanced" and "search" should be circled, whereas in other cases only one or neither of the attributes should be circled, as appropriate. The notion of strict balance considered in HW4 should be used here, and a search tree is defined as usual to be one whose inorder listing yields a nondecreasing list.

    a)

    Arrows are used below instead of circles, for historical consistency...
    
           1               balanced <--
          / \
         2   3             
        / \   \            search 
       4   5   6
    

    b)

           3               balanced <--
          / \
         2   4             
              \            search <--
               5
    

    c)

           4               balanced
          / \
         2   5             
        / \                search <--
       1   3    
    

  3. a) Fill in the blanks to complete the following recursive implementation of a non-member function of the Stack<Item> class named mypeek. The implementation may access Stack<Item> objects only through the public members of the Stack<Item> class, namely the constructor, copy constructor, push, pop, size, and is_empty methods. You may not use any previously implemented peek functions.
    
    template <class Item>
    Item mypeek(const Stack<Item>& s, size_t depth) {
    // Preconditions: s.size() > depth
    // Postconditions: The stack s has not been altered;
    //   the item stored in s at the given depth relative to the
    //   top of s (the top of s is at depth 0) has been returned
    //
    // Check precondition
       assert(s.size() > depth);
    //
    // Initialize a new stack t as a copy of s
       Stack<Item> t(s);
    //
    // Base case
       if (depth==0) {
          return t.pop();
       }
    //
    // Recursive case
       else {
          t.pop();
          return mypeek(t, --depth);  // depth-1 also works, depth-- doesn't
       }
    }
    
    

    b) Assuming that a correct implementation of the mypeek() function specified above in a) is available, write the output produced by the following program segment next to the word "Answer" below:

    
       Stack<int> mystack;
       for (int i=0; i<10; i++)
          mystack.push(i);
       for (int i=9; i>=0; i--)
          cout << mypeek(mystack, i) << " ";
    
       Answer: 0 1 2 3 4 5 6 7 8 9 
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

  4. Fill in the following implementation of the function named growtree so that it satisfies the specification shown. A full binary tree is one in which all non-leaf nodes have two children and all leaf nodes are at the same depth. The height of a tree is the greatest depth of any of its leaves; the root node is defined to be at depth 0.
    
    BinaryTreeNode* growtree(size_t n) {
    // Postcondition: a full binary search tree of height n
    //   has been constructed; all nodes of the tree contain '*';
    //   a pointer to the root of the tree has been returned
    //
       BinaryTreeNode *left_ptr, *right_ptr;
    //
    // Base case
       if (n==0) {
          left_ptr = NULL;
          right_ptr = NULL;
       }
    //
    // Recursive case
       else {
          left_ptr = growtree(n-1);
          right_ptr = growtree(n-1);
       }
    //
    // Below, create_node is the standard binary tree toolkit function
       return (create_node('*', left_ptr, right_ptr));
    }
    
    

  5. Circle the appropriate answer in each of the following cases.

    a) A stack is a data structure of the following type.

       FIFO          LIFO  <--
    

    b) The Queue ADT has an access method (public member) named:

       push          get_front  <--
    

    c) The maximum allowable number of formal template parameters within the same template function is

       1             2 or more  <--
    

    d) A full binary tree of height n has approximately the following number of nodes.

       2n <--        n2
    

    e) Dynamic arrays are a better implementation choice than linked lists in situations that require frequent insertions at a cursor and resizing.

       TRUE          FALSE <--
    

    f) The standard recursive implementation of the factorial function based on the recurrence relation
    n! = n*( (n-1)! ) requires a constant multiple of the following number of steps to compute the value n!.

       n <--         n2