CS140 Midterm 2

Instructions

  1. Write your name clearly at the top of the exam

  2. You must answer all the questions on the exam. The exam has 7 problems. Make sure that you have all 7 problems.

  3. Write your answers on the exam pages and hand in the exam when you are finished.

  4. You have until the end of the class period to finish the exam. When I call time you must immediately drop your pen/pencil and hand in your exam.

  5. Ensure that you write clearly and legibly. Failure to do so may result in the deduction of points.

  6. The exam is closed note, closed book, closed neighbor.

  7. Good luck!

  1. (20 points)
     
    array     singly-linked list     linked-list queue       linked-list stack
              doubly-linked list     circular array queue    array stack
    

    For each of the following questions choose the best answer from the above list. Assume that the size of an array is fixed once it is created, and that its size cannot be changed thereafter. Sometimes it may seem as though two or more choices would be equally good. In those cases think about the operations that the data structures support and choose the data structure whose operations are best suited for the problem. You may have to use the same answer for more than one question:

    1. ____________ The data structure you would use if you were writing software for a call center that ensured that calls are answered in a first-in, first-out order. You should assume that you have to be able to store an unlimited number of waiting callers.
    2. ____________ The data structure you would use if you wanted to store different purchase lots of an inventory item (e.g., printers) and when you sold them, you want to decrement the remaining quantity of the most recently purchased lot. For example, if you make 3 separate purchases of 20, 30, and 15 printers, and you then sell 5 printers, you want to decrement the lot of 15 printers so that it is now 10.
    3. ____________ The data structure you would use if you had a pre-sorted set of data with a known size and you wanted to use binary search to find whether or not certain keys existed in the data (in binary search you probe into the middle of the remaining data and then eliminate either the bottom or upper half of the data depending on the value of your key and the value of the element at the middle of the data).
    4. ____________ The data structure that you would use in a router to store and dispatch an incoming set of message packets from the network if you have a limited amount of memory to store the packets (packets that cannot be stored because there is not enough memory will be bounced back to the sender). Packets should be dispatched to the next router in the network in the order in which they are received.
    5. ____________ The data structure that is easiest to use if you need to read and store an unknown number of data items, and subsequently search this data structure for different keys.

  2. (10 points) Consider the following set of declarations:
    typedef struct {
      int x;
      char name[20];
      char *address;
    } FriendRecord;
    
    FriendRecord *friend;
    void *ptr;
    char input[20];
    
    Put an X next to any statement that is illegal, according to the compiler, and explain why it is illegal:

    1. friend = ptr;
    2. ptr = friend;
    3. ptr->x = 20;
    4. strcpy(friend->name, input);
    5. friend->name = strdup(input);

  3. (15 points) State the Big-O running times for the following pieces of code and briefly justify your answer. A sample answer might be:

    O(n3): the most time is spent in the three nested loops. Each loop iterates n times, and each iteration of the inner-most loop requires a constant amount of time.

    (a)
    min = -1; for (i = 0; i < n; i++) { if (a[i] < min) min = a[i]; } printf("min = %d\n", min);
    (b)
    a = 10; b = 20; c = a + b;
    (c)
    for (i = 0; i < n; i++) { if (array[i] > 0) { sum = 0; for (j = i; j < n; j++) { sum += array[j]; } printf("sum = %d\n", sum); } else printf("array[%d] = %d\n", i, array[i]); }
     

  4. (10 points) Programs A and B are analyzed and found to have the runnng times 2N and 1000N2, respectively. Answer the following questions (Note: you should not need a calculator to answer any of the following questions):

    1. Which program has the better guarantee on the running time, for large values of N (N > 10,000)? Why?
    2. Which program has the better guarantee on the running time, for small values of N (N < 10)? Why?
    3. If you did not know the size of the input, which program would you prefer? Why?
  5. (9 points) Suppose you have the following declaration for a list node:
    struct node {
      void *value;
      struct node *next;
    }; 
    struct node *my_node, *successor;
    
    Write a fragment of code that swaps my_node and its successor by adjusting only the links (and not the data). The diagram below shows the before and after order of the two nodes in the list. You may declare whatever temporary variables you need in order to perform the swap.
          Before:        ___________      _____________
                   <-----| my_node |<-----| successor |<-----
                   ----->|         |----->|           |----->
                         -----------      -------------
    
          After:         _____________      _____________
                   <-----| successor |<-----| my_node   |<-----
                   ----->|           |----->|           |----->
                         -------------      -------------
          
  6. (16 points) Consider the following declarations and function: push(Stack *s, int i); // push an integer i onto s int pop(Stack *s); // pop an integer off s and return its value bool isEmpty(Stack *s); // return true if the s is empty and false otherwise Please note that I have simplified the above API from my stack library to make it easier for you to deal with in this problem. In particular you may assume that you have a stack of integers, rather than a stack of void *'s. int mystery(Stack *stack) { char token[5]; int x; int a, b; int result; while (scanf("%s", &token) != EOF) { if (sscanf(token, "%i", &x) == 1) push(stack, x); else if (strcmp(token, "+") == 0) { if (!mystery1(stack, &a, &b)) return -1; push(stack, a+b); } else if (strcmp(token, "*") == 0) { if (!mystery1(stack, &a, &b)) return -1; push(stack, a*b); } } result = pop(stack); if (isEmpty(stack)) return result; else return -2; } bool mystery1(Stack *stack, int *x, int *y) { if (isEmpty(stack)) return false; *x = pop(stack); if (isEmpty(stack)) return false; *y = pop(stack); return true; }

    Suppose the input is:

    3 2 + 4 * 3 5 * + 
    
    1. What is the contents of stack after the second * is read and processed? Some of your entries may be empty. Fill the stack from bottom to top:
           ______________
           |            |
           |            |
           --------------
           |            |
           |            |
           --------------
           |            |
           |            |
           --------------
           |            |
           |            |
           --------------
           |            |
           |            |
           --------------
      
    2. Once mystery has read the full input, what does mystery return?
    3. Suppose the input were instead 3 2 + 4. What would mystery return in this case?
    4. Suppose the input were instead 3 2 + *. What would mystery return in this case?
    5. mystery returns three different values--result, -1, or -2--depending on the outcome of its checks. How would your calling program interpret each of these return values? That is, if your program had to print a message explaining the meaning of the return value, what would it say. Be concise (you may want to defer this question to the end of the test because you might have to devise a couple sample input sequences to figure it out and that could take some time).

      1. -1:
      2. -2:
      3. return:

  7. (20 points) You are given two doubly linked lists, L1 and L2, of integers, both sorted in ascending order. You should write a function named setDifference(L1, L2) that deletes any element from L1 that matches an element in L2. For instance, if you are given the two lists:
    L1: (6, 8, 10, 20, 25, 30, 41, 66)
    L2: (3, 6, 10, 33, 38, 41, 55, 66, 78, 90)
    
    then your modified L1 will be:
    L1: (8, 20, 25, 30)
    
    L2 will remain unchanged. Note that after setDifference is finished, L1 contains only its original elements that were not contained in L2. Write the function setDifference(L1,L2) using my dllist library.

    Here is some helpful information:

    1. L1 and L2 are pointers to Dllists.
    2. Assume that dll_val returns an int and not a void *. Hence dll_val(node) will return the integer value of that node.
    3. The function does not return anything nor does it print anything. It achieves its result by modifying the two lists.
    4. For maximum points, you should take advantage of the fact that the elements of L1 and L2 are sorted in ascending order and traverse each list only once. If you cannot figure out how to do this, you can traverse L1 and L2 multiple times for 16 points.
    5. You need to show me your function declaration and definition. Do not show me include files, statements to read data, etc. Assume L1 and L2 have been created for you by the calling function.