Source of profiler_search_linear.cpp


  1: /** @file profiler_search_linear.cpp
  2: Perform timing and operation counts for linear searches.
  3: */

  5: #include <iostream>
  6: #include <iomanip>
  7: #include <string>
  8: #include <vector>
  9: using namespace std;

 11: #include "utilities.h"
 12: using Scobey::Pause;
 13: using Scobey::ReadInt;
 14: using Scobey::userSaysYes;
 15: using Scobey::OperationCounter;
 16: using Scobey::RandomGenerator;
 17: using Scobey::Stopwatch;

 19: //Global variables permitted
 20: //These global variables are permissible for the following reasons:
 21: //There is only one of each used throughout the program and each is used
 22: //in the same way each time it is used, much like the "global object" cout
 23: //is used everywhere throughout a program to display output on the screen.
 24: OperationCounter  counter;
 25: Stopwatch         timer;
 26: bool counter_ON = false;
 27: bool timer_ON   = false;


 30: //Function prototypes
 31: void Search
 32: (
 33:     vector<int>& v //in
 34: );
 35: /**<
 36: Handle the high-level interaction with the user for each search.
 37: @param v The current vector of integer values through which to search.
 38: @pre v has been initialized.
 39: @post A search for some value in v has been performed.
 40: */


 43: void SearchLinear
 44: (
 45:     const vector<int>& v, //in
 46:     int targetValue,      //in
 47:     int firstPosition,    //in
 48:     int lastPosition,     //in
 49:     int& targetPosition,  //out
 50:     bool& targetFound     //out
 51: );
 52: /**<
 53: Perform a search for a target value in the vector of integers.
 54: @param v The current vector of integers through which to search.
 55: @param targetValue The value for which to search.
 56: @param firstPosition The first postion of the range to search.
 57: @param lastPosition The last position of the range to search.
 58: @param targetPosition The position where the target value was found.
 59: @param targetFound Indicates if the target was found.
 60: @pre v, targetValue, firstPosition and lastPosition have been initialized.
 61: It must also be true that 1 <= firstPosition <= lastPosition <= v.size().
 62: @post Either targetFound == true and targetValue is located at position
 63: targetPosition (i.e., at v[targetPosition-1]), or targetFound == false
 64: and targetPosition == lastPostion+1. Note that in this latter case
 65: targetPosition must not be used.
 66: */


 69: void DisplayValues
 70: (
 71:     const vector<int>& v //in
 72: );
 73: /**<
 74: Display the sequence of integers through which the searches will
 75: be performed.
 76: @param v The current vector of integers through which to search.
 77: @pre v has been initialized.
 78: @post The integer values in v have been displayed, 10 per line.
 79: */


 82: void DisplayStatistics();
 83: /**<
 84: Display results of comparison counting and timing if these actions
 85: have been performed.
 86: @pre The following global objects and variables have been declared:
 87: - timer, an object of the Stopwatch class
 88: - timer_ON, a "switch" variable of type bool
 89: - counter, an object of the OperationCounter class
 90: - counter_ON, a "switch" variable of type bool
 91: @post If counter_ON is true, the number of comparisons recorded by
 92: counter are displayed in summary form. And, if timer_ON is true,
 93: the time taken by the algorithm is displayed. If neither counter_ON
 94: nor timer_ON is true, the function does nothing (except provide a
 95: pause if actually called).
 96: */


 99: int main()
100: {
101:     cout << "\nThis program is a \"search profiler\". It uses a linear "
102:         "search algorithm to\nsearch through a randomly generated sequence "
103:         "of integers for a target value\nsupplied by the user, and then "
104:         "reports the first position where the target\nvalue was found, or "
105:         "that the target value was not present. It can also time\na search "
106:         "and/or count the number of comparisons performed."
107:         
108:         "\n\nAll values may be displayed, if the user so wishes. "
109:         "They are shown 10 per\nline, with each value right-justified "
110:         "within a fieldwidth of 7 spaces. Thus\neach generated value, "
111:         "including the minus sign, if any, should not occupy\nmore than "
112:         "6 spaces.\n";
113:     Pause();

115:     vector<int> v;    //Sequence of integer values to be searched
116:     int numberOfInts; //Number of integer values in search sequence
117:     int low, high;    //Range of values in search sequence

119:     ReadInt("Enter required number of integers for the sequence to "
120:         "be searched: ", numberOfInts);
121:     ReadInt("Enter lower bound for that sequence: ", low);
122:     ReadInt("Enter upper bound for that sequence: ", high);
123:     RandomGenerator g;
124:     if (userSaysYes("Would you like to \"seed\" the random generator?"))
125:     {
126:         int seedValue;
127:         ReadInt("What seed value would you like to use? ", seedValue);
128:         g.reset(seedValue);
129:     }
130:     for (int i=1; i<=numberOfInts; i++)
131:         v.push_back(g.getNextInt(low, high));

133:     const string CONTINUE_QUERY =
134:         "Would you like to search for another target value?";
135:     do
136:     {
137:         if (userSaysYes("Display the values?"))
138:             DisplayValues(v);
139:         timer_ON = userSaysYes("Time the search?");
140:         counter_ON = userSaysYes("Count the operations?");
141:         Search(v);
142:         if (timer_ON || counter_ON) DisplayStatistics();
143:     }
144:     while (userSaysYes(CONTINUE_QUERY));
145: }


148: void DisplayValues
149: (
150:     const vector<int>& v  //in
151: )
152: {
153:     cout << "\nHere is the current list of integer values:\n";
154:     const int NUMBER_PER_LINE = 10;
155:     vector<int>::size_type i;
156:     for (i = 0; i<v.size(); i++)
157:     {
158:         cout << setw(7) << v.at(i);
159:         if ((i+1) % NUMBER_PER_LINE == 0) cout << endl;
160:     }
161:     //Note that the value of i in the following is the same as
162:     //the last value of i+1 in the body of the above loop.
163:     cout << ((i % NUMBER_PER_LINE == 0) ? "\n" : "\n\n");
164: }


167: void DisplayStatistics()
168: {
169:     if (counter_ON) counter.displayAllCounts();
170:     if (timer_ON) cout << "Time taken = " << timer.getSeconds()
171:         << " seconds.\n\n";
172:     Pause();
173: }


176: void Search
177: (
178:     vector<int>& v //in
179: )
180: {
181:     int targetValue;
182:     ReadInt("\nFor what value would you like to search? ", targetValue);

184:     cout << "Between what two positions would you like to search?\n";
185:     int firstPosition, lastPosition;
186:     ReadInt("Enter first position here: ", firstPosition);
187:     ReadInt("Enter last position here: ", lastPosition);

189:     bool targetFound;
190:     int targetPosition;
191:     if (timer_ON) timer.start();
192:     SearchLinear(v, targetValue, firstPosition, lastPosition,
193:         targetPosition, targetFound);
194:     if (timer_ON) timer.stop();

196:     cout << "\nValue " << targetValue;
197:     if (targetFound)
198:         cout << " located at position " << targetPosition << ".\n";
199:     else
200:         cout << " not found.\n";
201:     Pause();
202: }


205: void SearchLinear
206: (
207:     const vector<int>& v, //in
208:     int targetValue,      //in
209:     int firstPosition,    //in
210:     int lastPosition,     //in
211:     int& targetPosition,  //out
212:     bool& targetFound     //out
213: )
214: {
215:     if (counter_ON) counter.reset();

217:     int index = firstPosition-1;
218:     while (index < lastPosition  &&  targetValue != v.at(index))
219:     {
220:         ++index;
221:         if (timer_ON) timer.delay(10);
222:         if (counter_ON) counter.incrementComparisons();
223:     }

225:     if (timer_ON) timer.delay(10);
226:     if (index < lastPosition) counter.incrementComparisons();
227:     //Since if the target value is found, the value comparison
228:     //in the while-condition is not counted in the loop body.

230:     targetFound = (index < lastPosition);
231:     targetPosition = index+1;
232: }

234: /*Here is the essential code of the algorithm, repeated for clarity:
235: ====================================================================
236: int index = firstPosition-1;
237: while (index < lastPosition  &&  targetValue != v.at(index))
238:     ++index;
239: targetFound = (index < lastPosition);
240: targetPosition = index+1;
241: */

243: //Show that the replacement shown below for the while condition
244: //in the above loop does not work in all cases and explain where
245: //and why things go wrong.
246: //while (targetValue != v.at(index)  &&  index <= lastPosition-1)