Final Examination Solution

Com 1201 – Fall 2002 – Jeff Raab

 

Section 1 – Java programming

 

(10)                  1.         Consider a type of array named a Power-2-Array.  An array of int values, a, is defined to be a Power-2-Array if the sum of its contents is equal to 2a.length.

 

                                    Write a public method below named power2Array that takes an array of int values named a and has a return type of boolean.  Your method must return true if the given array is a Power-2-Array by the above definition, or false in every other case.  Your code must be complete, correct, documented, and as efficient as possible. 

 

                                    Analyze your method by listing its actual number of steps in the worst case, and by using Big-Oh notation to generalize the number of steps in the worst case.

 

/**

 * Returns true if the sum of the values in the given array

 * is equal to 2^length of the array.

 * @example power2Array({1,1}) returns true

 * @example power2Array({1,2}) returns false

 * @example power2Array({}) returns false

 * @example power2Array(null) returns false

 * @param a array of values to test

 */

public boolean power2Array(int[] a) {

     if (a == null) {

           return false;

     }

 

     int sum = 0;

     int power = 1;

 

     for (int i = 0; i < a.length; i++) {

           sum += a[i];

           power *= 2;

     }

 

     return (sum == power);

}

 

 

                                    The actual number of steps in the worst case  is 2n + 4 .

 

                                    Using Big-Oh notation, this generalizes to                      O(n)  .


Section 2 – Implementing an ADT

 

(30)      Write an implementation of the Queue ADT, in Java, that uses an array of Objects to hold the contents of the queue.  Your implementation must never fail to enqueue an Object due to insufficient space in the array of contents.  Your implementation does not have to reduce the length of the array at any time, though it is acceptable for it to do so if you choose.

 

            Your implementation must be complete, correct, documented, and as efficient as possible given the constraints of the problem.  Include in your documentation for each method an analysis of the worst case running time of the method, using Big-Oh notation.  The details of the Queue ADT are included on the final page of the examination.

 

            Use the remainder of this page and the next page to provide your answer.

 

/**

 * Queue implementation using an array to store the elements.

 * @author Jeff Raab

 */

public class ArrayQueue implements QueueADT {

 

     /** Elements on this. */

     protected Object[] elements = new Object[10];

 

     /** Index of front element in this. */

     protected int front = -1;

 

     /** Index of back element in this. */

     protected int back = -1;

 

     /** Constructs an empty queue. */

     public ArrayQueue() {}

 

     /**

      * Enqueues the given element on this.

      * @param o object to enqueue

      */

     public void enqueue(Object o) {

          back = after(back);

          elements[back] = o;

 

          if (front == -1) {

               front = 0;

          }

     }

 

     /** Returns the front element on this. */

     public Object front() {

          if (isEmpty()) {

               throw new RuntimeException(“Queue is empty”);

          }

 

          return elements[front];

     }

 

     /** Removes and returns the front element on this. */

     public Object dequeue() {

          if (isEmpty()) {

               throw new RuntimeException(“Queue is empty”);

          }

 

          Object f = elements[front];

          front = after(front);

 

          if (size == 0) {

               front = -1;

               back = -1;

          }

     }

 

     /** Returns the size of this. */

     public int size() {

          if (back >= front) {

               return (back – front);

          }

         

          return (back + elements.length – front);

     }

 

     /** Returns whether or not this is empty. */

     public boolean isEmpty() {

          return (size() == 0);

     }

    

     /**

      * Returns the array index after the given index.

      * @param i index in the array

      */

     private int after(int i) {

          return ((i + 1) % elements.length);

     }

}


Section 3 – Short answer questions

 

(10)                  1.         Is it possible to implement the Stack ADT using one or more implementations of the Queue ADT?  In other words, is it possible to implement the Stack ADT by using only one or more queues to hold the contents of the stack?  You may use only the Queue ADT methods of the queues to implement the methods specified in the Stack ADT.  You may assume that a Queue ADT implementation exists that is complete and correct.

 

                                    Write your answer below.  If yes, describe in reasonable detail how such a Stack ADT implementation would be implemented, including at least a short explanation for each method in the ADT.  If no, describe in reasonable detail why one or more Queue ADT implementations are insufficient to implement the Stack ADT.

 

Yes, it is possible to implement the Stack ADT using 2 implementations of the Queue ADT.  One of the queues will be used to store the elements and the other to hold them temporarily during the pop and top methods.  The push method would enqueue the given element onto the storage queue.  The top method would transfer all but the last element from the storage queue onto the temporary queue, save the front element of the storage queue to be returned, transfer the last element to the temporary queue, then transfer all elements back to the storage queue.  The pop method would do the same as top, except instead of transferring the last element onto the temporary queue after saving it for return, that last element would be discarded.


(10)                  2.         Describe in reasonable detail a way to implement the Dictionary ADT such that the insertItem, findElement, and removeElement methods would all run in O(1) time, assuming that all of the keys associated with elements in the structure are integers in the range [25, 75].  You do not have to ensure that the remaining Dictionary ADT methods would have any particular running times, and you do not have to describe how those remaining methods would be implemented.

 

                                    Describe how much memory would be used by such a structure, both specifically and in Big-Oh notation.  For example, if you were to describe an unsorted sequence implementation of the Dictionary ADT, you would state that your structure would use 1 sequence of size n, which is O(n). 

 

Given the range of keys, a hash table array of length 51 could be used to implement the Dictionary ADT.  The hash function for the table would be h(k) = k – 25.  Separate chaining would be the collision handling strategy for the hash table, with unsorted lists used to hold the elements associated with the key represented by that index.  insertItem would hash the key and insert into the unsorted list at the resulting index: O(1).  findElement would hash the key and return the first element of the list, unless it was empty: O(1).  removeElement would hash the key and remove the first element of the list, unless it was empty: O(1).

 

The memory used by this structure is an array of 51 lists, which is 51 + O(n) units of memory, or O(n).


Section 4 – Diagrammatic questions

 

(5)                    1.         List the order in which the contents of the following tree would be visited, for each of the given traversals:

 

 

Traversal

Visit order

 

Preorder

G

V

S

J

M

X

R

Z

A

T

 

Postorder

J

S

M

V

Z

A

R

T

X

G

 

Inorder

S

J

V

M

G

Z

R

A

X

T

 

 

(5)                    2.         List the order in which the given keys would be contained in a Priority Queue ADT implemented using a sorted sequence, where keys are ordered in nondecreasing order of their priority value.  You should ignore the elements associated with the given keys as they could be any objects, and they do not affect the resulting order.

 

                                    For this problem the priority value of a key is defined as its minimum absolute value difference from the various powers of 2.  For example, the priority value of the key 12 is 4, as it is 4 away from both 8, 23, and 16, 24.  The priority value of the key 66 is 2, as it is 2 away from 64, 26.  A table of the powers of 2 is below, for your reference:

 

k

0

1

2

3

4

5

6

7

8

9

10

2k

1

2

4

8

16

32

64

128

256

512

1024

 

                                    Fill in the sequence diagram below with your answer, given the following list of keys in random order:

 

Keys

94

28

43

256

71

48

462

11

0

84

54

 

Sorted sequence priority queue

 

 

 

 

 

 

 

 

 

 

 

 

 

 

256

0

11

28

71

54

43

48

84

94

462

 

 

0

1

2

3

4

5

6

7

8

9

10

 

 

 

 

 

 

 

 

 

 

 

 

 

 

size = 11

 


(5)                    3.         Draw the heap that results from removing a minimum key from the heap shown below.  Circle each node on the given heap diagram that was removed or had its key swapped in this process.  You should ignore the elements associated with the given keys as they could be any objects and do not affect the resulting order.

 

 

                                    

 

 

(5)                    4.         List the contents of the array for an open addressing hashtable using the linear probing style of collision handling, after performing the given Dictionary ADT operations in order.  Use the following hash function:

 

h(k) = | 2k + 5 | mod 11

 

                                    You should ignore the elements associated with the given keys as they could be any objects and do not affect the resulting order.  Place an X in the array to indicate an empty location that used to contain a key. 

 

                                    Fill in the following array diagram with your final answer, for these given operations:

 

Operations

insertItem(2)

insertItem(14)

insertItem(2)

removeAllElements(2)

removeElement(0)

insertItem(13)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

14

 

 

 

 

 

 

 

 

13

X

 

 

0

1

2

3

4

5

6

7

8

9

10

 

 

 

 

 

 

 

 

 

 

 

 

 

 

length = 11

 


Section 5 – Data structures

 

For each situation below, list the ADT you would choose for the specified task, and the implementation of that ADT that would provide the most efficient running time for each of the operations listed in the problem.  Please use asymptotic analysis for the running time, and use Big‑Oh and Big‑Theta as appropriate.

 

(10)                  1.         You are employed by a software company designing an application for use by produce wholesalers.  Your job is to implement the data structure used to store the inventory of the warehouse containing the produce.  The data structure must be able to add a product with an associated code indicating its likelihood to spoil, remove a product that is most likely to spoil (to ship it from the warehouse), and return the overall number of products in the inventory.  No other functionality is needed.

 

            Your choice of ADT would be:                             Priority Queue ADT

 

            Your choice of implementation would be:               Heap

 

Operation

Method in ADT used to implement

Running time

Add a product and its code

insertItem

O(log n)

Remove a product likely to spoil

removeMin

O(log n)

Return the number of products

size

O(1)

 

(10)                  2.         You are employed by a software company designing an application for use by taxicab dispatchers.  Your job is to implement the data structure used to associate customers with taxicabs.  The data structure must be able to associate a customer’s address with a taxicab’s number, find the address associated with a taxicab’s number, and remove the association between an address and a taxicab number (when the customer has been delivered to its destination.  No other functionality is needed.

 

            Your choice of ADT would be:                             Dictionary ADT

 

            Your choice of implementation would be:              Hash table

 

Operation

Method in ADT used to implement

Running time

Associate address with taxicab

insertItem

O(n)

Find address associated with taxi

findElement

O(n)

Remove address and taxicab association

removeElement

O(n)

 


 


Stack ADT

 

void push(Object)

Object pop()

Object top()

int size()

boolean isEmpty()

 

Queue ADT

 

void enqueue(Object)

Object dequeue()

Object front()

int size()

boolean isEmpty()

 

Vector ADT

 

void insertAtRank(int, Object)

Object removeAtRank(Object)

Object elementAtRank(int)

Object replaceAtRank(int, Object)

int size()

boolean isEmpty()

 

List ADT

 

Position insertFirst(Object)

Position insertLast(Object)

Position insertBefore(Position, Object)

Position insertAfter(Position, Object)

Object remove(Position)

Position first()

Position last()

boolean isFirst(Position)

boolean isLast(Position)

Object replaceElement(Position, Object)

void swapElements(Position, Position)

int size()

boolean isEmpty()

 

Sequence ADT

 

(Vector ADT + List ADT +)

Position atRank(int)

int rankOf(Position)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Priority Queue ADT

 

void insertItem(Comparable, Object)

Object removeMin()

Comparable minKey()

Comparable minElement()

int size()

boolean isEmpty()

 

Dictionary ADT

 

void insertItem(Object, Object)

Object removeElement(Object)

Object[] removeAllElements(Object)

Object findElement(Object)

Object[] findAllElements(Object)

Object [] keys()

Object[] elements()

int size()

boolean isEmpty()