CS302 Midterm, Fall, 2016

James S. Plank

Answers and Grading

Question 1: 20 points

Part A: The links define the following instance of disjoint sets:

So, the answer is:

Part B: Union by size. This is because the ranks[] entry of the heads of the set are equal to the sets' sizes. They clearly don't equal the heights (e.g. the height of the set rooted by 1 is not 9), and even if you used path compression, there's no way to get a rank of 9 with this few elements.

Part C: See the picture:

Part D: The first thing we do is view the vector as a heap:

Now, you call percolate_down() on the nodes with 40, 46 and 71:

Next, you call percolate_down() on the nodes with 56 and 86:

And finally, you call percolate_down() on the root:

Print that out as a vector:

{ 5, 10, 68, 32, 16, 71, 75, 40, 56, 46, 20, 86 }

Doing this by calling Push() on each element of the vector is not only the incorrect way to do it, it's a huge pain, as you have to call percolate_up() 11 times. If you did that, the proper answer was:

{ 5, 16, 10, 40, 20, 68, 71, 75, 46, 56, 32, 86 }


Question 2: 20 points

I reiterated during the test: I wanted the running time of the procedure. That is specified clearly on the exam. That will be defined by the running time of the most costly operation, but that doesn't mean it is equal to the running time of the most costly operation. For example, in Proc_F(), the most costly operation is the Pop() call, which is O(log n). However, you're calling Pop() n times, so the running time of the procedure is O(n log n).

Grading here was 2 points per part. I gave some partial credit.

Also, I took off if your answers demonstrated that you didn't really "get" big-O -- answers like O(n+3), or O(n/2), or O(n) + O(n2).


Question 3: 20 points

Part A: This one follows the enumeration lecture notes. Let l be equal to s.size(). You will enumerate all numbers from 0 to ln-1, and treat each number like a n-digit number in base l. You'll extract those digits with div and mod, and use them as indices into s. The program q3.cpp implements proc() and also implements a main() that allows you to specify n and s on the command line.

void proc(int n, string s)
  int top;
  int i, j, index;

  /* Calculate the total number of strings. */

  top = 1;
  for (i = 0; i < n; i++) top *= s.size();

  /* Now, enumerate a separate index for each string.  You
     will calculate the individual characters using div/mod,
     as explained in the enumeration lecture notes.  */

  for (index = 0; index < top; index++) {
    i = index;
    for (j = 0; j < n; j++) {
      printf("%c", s[i%s.size()]);
      i /= s.size();

UNIX> g++ -o q3 q3.cpp
UNIX> q3 2 a
UNIX> q3 2 ab
UNIX> q3 2 abc
UNIX> q3 3 ab

Part B: ln, where l equals s.size().


Part A was worth 16 points, and Part B was worth 4. If you gave the right answer for Part B, but it didn't match your implementation, then you got 3 points. I gave partial credit to power set enumerations, which typically got confused, because you didn't know what to do with n.

Question 4: 16 points

The answers for both questions 4 and 5 are in q45.cpp. Question 4 is straightforward bit arithmetic:

vector <int> do_transpose(vector <int> m)
  vector <int> rv;
  int i, j;

  rv.resize(m.size(), 0);
  for (i = 0; i < m.size(); i++) {
    for (j = 0; j < m.size(); j++) {
      if (m[i] & (1 << j)) {
        rv[j] |= (1 << i);
  return rv;


As always, I gave partial credit.

Question 5: 20 points

Question 5 is a nuts and bolts program that uses sscanf() or stringstreams to read the command line and check the formatting. There are three errors that I can think of, and you should test for each:

int main(int argc, char **argv)
  int i, v, mask;
  vector <int> m;
  vector <int> t;

  /* Reading the command line.  This loop was worth 12 points. */

  for (i = 1; i < argc; i++) {
    if (sscanf(argv[i], "0x%x", &v) != 1) {
      printf("Bad command line argument %s\n", argv[i]);

  /* Too many words on the command line. Two points. */
  if (m.size() > 32) {
    printf("Too many items in m: must be <= 32\n");

  /* Checking for stray bits. Two points. */

  if (m.size() < 32) {
    mask = (1 << m.size()) - 1;
    for (i = 0; i < m.size(); i++) {
      if ((m[i] & mask) != m[i]) {
        printf("Bad item -- 0x%x -- too many bits set.\n", m[i]);

  /* Call do_transpose and print. Four points. */

  t = do_transpose(m);
  for (i = 0; i < t.size(); i++) printf("0x%x\n", t[i]);
  return 0;