CSCI 159 Quiz 3 Sample Solutions Wednesday lab


Question 1 Arrays [7 marks]
Write the body of the transform function below so that it behaves as dictated by the comments.
// for each of the first k elements of the two arrays, arr1 and arr2,
//    subtract the value of arr2's element from arr1's element
//    (modifying the content in arr1)
// e.g. if k was 4 and the first 4 elements of arr1 were { 9, 6, 3, 1 }
//    and the first 4 elements of arr2 were { 1, 0, 3, 2 }
// then after running subFrom the first 4 elements of arr1 would be { 8, 6, 0, -1 }
//    (and the contents of arr2 would be unchanged)
void subFrom(double arr1[], double arr2[], int k)
Correction the name of the function is subFrom, not transform

Sample solution


void subFrom(double arr1[], double arr2[], int k)
{
   for (int pos = 0; pos < k; pos++) {
       // subtract arr2 element from arr1 element,
       //    put result back as new arr1 element
       arr1[pos] = arr1[pos] - arr2[pos];
   }
}

Question 2 Searching [7 marks]
The functions linear and binary below can be used to perform linear searches and binary searches on portions of an array, with the binary search assuming the array contents are already sorted in non-decreasing order.
Both functions assume that lowpos and hipos specify the first and last positions of the portion of the array that needs to be searched.

int linear(float arr[], int lowpos, int hipos, float target)
{
   for (int pos = lowpos; pos <= hipos; pos++) {
       if (arr[pos] == target) {
          return pos;
       }
   }
   return -1;
}
int binary(float arr[], int lowpos, int hipos, float target)
{
   while (lowpos < hipos) {
      int mid = (lowpos + hipos) / 2;
      if (arr[mid] == target) {
         return mid;
      } else if (arr[mid] < target) {
         lowpos = mid+1;
      } else {
         hipos = mid-1;
      }
   }
   return -1;
}

Suppose we have an int array name ARR whose size is M+N, and in which the first M values are sorted in non-increasing order (i.e. the opposite to what binary expects) and the last N values are sorted in non-decreasing order.
For example, with M=5 and N=6, ARR might contain { 206, 19, 8, 7, 3 } in the first 5 positions and { -3, 2, 18, 32, 96, 97 } in the remaining 6 positions.

(i) If we were looking for the value specified by variable T, identify which of the following calls would most appropriately search the first M positions of ARR and why: linear(ARR, 0, M-1, T) or binary(ARR, 0, M-1, T).

(ii) If we were looking for the value specified by variable T, identify which of the following calls would most appropriately search the last N positions of ARR and why: linear(ARR, M, N-1, T) or binary(ARR, M, N-1, T).

(iii) Write the modSearch function below, using appropriate calls to linear and binary to search arrays that are formatted in this unusual two-segment style.
I.e. modSearch calls either linear or binary on the first M elements and returns that position if the search was successful, otherwise it calls either linear or binary on the last N elements and returns the result of that search.)
int modSearch(float arr[], int M, int N, float target)
Correction: in (ii) the third parameter in the calls should be M+N-1 rather than N-1

Sample solution

(i) Use linear on the first M since they aren't sorted in the direction
    needed by binary so binary can't reliably work

(ii) Use binary on the last N since they are correctly sorted for binary
     and it will be more efficient than linear would

(iii) idea: call linear on the first M, if it finds it then we're done,
            otherwise call binary on the last N

      int modSearch(float arr[], int M, int N, float target)
      {
          int res = linear(arr, 0, M-1, target);
          if (res !=  -1) {
             return res;
          } else {
             return binary(arr, M, M+N-1, target);
         }
      }

Question 3 Sorting [6 marks]
The bubbleSort code below follows a typical pattern for re-arranging the contents of an array into sorted order, but contains a flaw.
(Assume the swap function already exists and is correct and that the appropriate libraries and using statements are in place.)
// sort the data in just the first N elements of the given array,
//    putting them in non-decreasing order
void sortBeginning(int arr[], int N)
{
   for (int i = 0; i < N; i++) {
       cout << "Pass " << i << ":";
       for (int j=1; j < N; j++) {
           if (arr[i-1] < arr[i]) {
              swap(arr[i], arr[i-1]);
           }
           cout << " " << arr[i];
       }
       cout << endl;
   }
}

(i) Show the output that would be generated by the first two passes through the outer loop of sortBeginning if the following code segment ran:
    int data[6] = { 8, 5, 9, 6, 3, 1 };
    sortBeginning(data, 4);

(ii) Explain what appears to be functionally wrong with the bubblesort code and outline a simple fix.

Sample solution

(i)  Working through the code line by line for the first two passes:

     On the first pass, i=0, it goes through j values 1 to N-1
        each time it compares arr[i-1] to arr[i],
           but it should be comparing based on j (the element position) not i (the pass number)
        on the very first pass, when i is 0, this means it's comparing
           arr[0-1] to arr[0], i.e. it's looking in arr[-1], which is off the bottom of the array
        the value there could be anything, 0, -1, some garbage, etc
           and in this case if it is anything less than 8 it will get swapped into arr[0]
        e.g. if the value there is 0 then we'll get 0 swapped into arr[0] and 8 swapped
             into the memory space before the array (doing who knows what there...)
        So the first time it hits cout it prints arr[i], i.e. arr[0], e.g. 0 (the garbage value)

        On the next pass through the inner loop the swap wouldn't swap anything
           since it's comparing arr[-1] and arr[0] again and has already swapped
           them if arr[-1] < arr[0]
        when it hits the cout it prints arr[0] again (since i is still 0)
        and again on the third pass

     So the first pass output is
        Pass 0: 0 0 0

     On the second pass it goes through a similar process,
        using i=1 and j values 1,2,3
     in this case we again get
        Pass 1: 0 0 0
     though at least this time it's not looking off the bottom end of the array

(ii) The first problem is that it's using the wrong index variable for
         everything inside the inner loop, it should be using j's not i's
     Fix: inside the inner for loop change all the i's to j's

     The second problem is that it's sorting backwards, 
         right now it says if (arr[i-1] < arr[i]) then swap them,
            which is the opposite of what we'd want
     Fix: change the < to >