Download
slide1 n.
Skip this Video
Loading SlideShow in 5 Seconds..
Program Memory Allocation PowerPoint Presentation
Download Presentation
Program Memory Allocation

Program Memory Allocation

91 Vues Download Presentation
Télécharger la présentation

Program Memory Allocation

- - - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

  1. Program B’s Run-Time Stack  (Room for B’s growth)  Program B’s Data Heap Program B Program A’s Run-Time Stack  (Room for A’s growth)  Program A’s Data Heap Program A Operating System Program Memory Allocation Each program being executed on a computer is allocated extra space which it could use for its stack of function calls, and/or for “dynamically” expanding its use of memory for data. The memory used for data is known as a “heap”. CS 150

  2. int yippy(int &yoo, int boo) { int i; for (i = 1; i < boo; i++) yoo += i; return boo + yoo; } yoo: boo: 5 i: 5 int snippy(int snoo) { int hep = yippy(snoo,5); if (hep > 0) return hep; else return 0; } snoo: 7 hep: ??? void main() { int snap = 7; int yap = 10; int blap = 100; blap = snippy(snap); yippy(yap, blap); zippy(yap); } snap: 7 yap: 10 blap: 100 A Program’s Run-Time Stack Program XYZ: void main() { int snap = 7; int yap = 10; int blap = 100; blap = snippy(snap); yippy(yap, blap); zippy(yap); } int snippy(int snoo) { int hep = yippy(snoo,5); if (hep > 0) return hep; else return 0; } void yippy(int &yoo, int boo) { int i; for (i = 1; i < boo; i++) yoo += i; return; } void zippy(int zoo) { cout << zoo << endl; } CS 150

  3. Recursion It is sometimes useful to have a function call itself, making it a recursive function. This approach often enables the programmer to solve a problem by repeatedly solving smaller, more manageable versions of the problem, until the original problem’s solution becomes apparent. Care must be taken when using recursion, however. Because a new incarnation of the function is placed upon the run-time stack each time the function is recursively called, there is a danger that the stack will overflow. To prevent this from happening, the function must contain a termination condition, which will recognize when the recursion should halt, and pop the current incarnation of the recursive function off of the run-time stack. CS 150

  4. Recursion Example #1: Factorial //////////////////////////////////////////////////////////////////////////// // Program file: factorial.cpp // // This program queries the user for a non-negative integer and then uses // // a recursive function to calculate the factorial of the input value. // //////////////////////////////////////////////////////////////////////////// #include <iostream> #include <iomanip> using namespace std; int factorial(int n); //////////////////////////////////////////////////////////// // The main function asks the user for a value, calls the // // recursive factorial function, and outputs the result. // //////////////////////////////////////////////////////////// void main() { int number, result; cout << "Enter a non-negative integer for factorial computation: "; cin >> number; while (number < 0) { cout << "I said, enter a NON-NEGATIVE integer: "; cin >> number; } cout << endl; result = factorial(number); cout << "FINAL RESULT: " << number << "! = " << result << endl << endl; } CS 150

  5. Factorial (Continued) ///////////////////////////////////////////////////////////////////////////// // Function factorial recursively calculates the factorial of parameter n, // // outputting entering and exiting messages to demonstrate to the user the // // recursive function calls which make the final calculation possible. // ///////////////////////////////////////////////////////////////////////////// int factorial(int n) { static int indent = 0; int result; cout << setw(indent) << "" << "ENTERING FACTORIAL ROUTINE WITH N = ” << n << endl << endl; if ((n == 1) || (n == 0)) { cout << setw(indent) << "" << "EXITING FACTORIAL ROUTINE WITH N = " << n << ", " << n << "! = " << 1 << endl << endl; indent -= 4; return 1; } else { indent += 4; result = n * factorial(n - 1); cout << setw(indent) << "" << "EXITING FACTORIAL ROUTINE WITH N = " << n << ", " << n << "! = " << result << endl << endl; indent -= 4; return result; } } CS 150

  6. Factorial (Continued) CS 150

  7. int factorial (int n) { if ((n == 1) || (n == 0)) return 1; else : } int factorial (int n) { if ((n == 1) || (n == 0)) return 1; else { result = n * factorial(n-1); return result; } } n: 1 result: ? n: 4 result: 4*? int factorial (int n) { if ((n == 1) || (n == 0)) return 1; else { result = n * factorial(n-1); return result; } } n: 2 result: 2*? int factorial (int n) { if ((n == 1) || (n == 0)) return 1; else { result = n * factorial(n-1); return result; } } n: 5 result: 5*? int factorial (int n) { if ((n == 1) || (n == 0)) return 1; else { result = n * factorial(n-1); return result; } } n: 3 result: 3*? void main() { : result = factorial(number); : } number: 5 result: ? Tracing Through Factorial’s Run-Time Stack CS 150

  8. Recursion Example #2: Exponentiation ////////////////////////////////////////////////////////////////////////////// // Program file: exponent.cpp // // This program queries the user for a floating-point base and an integer // // exponent, and then uses a recursive function to calculate the value of // // the base raised to the power. // ////////////////////////////////////////////////////////////////////////////// #include <iostream> #include <iomanip> using namespace std; double exponentiate(double base, int power); ////////////////////////////////////////////////////////////// // The main function asks the user for a value, calls the // // recursive exponentiate function, and outputs the result. // ////////////////////////////////////////////////////////////// void main() { double base, result; int power; cout << "Enter a floating-point base value: "; cin >> base; cout << "Enter an integer exponent: "; cin >> power; cout << endl; result = exponentiate(base, power); cout << endl << "FINAL RESULT: " << base << '^' << power << " = " << result << endl << endl; } CS 150

  9. Exponentiation (Continued) ////////////////////////////////////////////////////////////////////////////// // Function exponentiate recursively calculates the value of raising // // parameter base to the parameter power's exponent, outputting entering // // and exiting messages to demonstrate to the user the recursive function // // calls which make the final calculation possible. // ////////////////////////////////////////////////////////////////////////////// double exponentiate(double base, int power) { static int indent = 0; double result; cout.setf(ios::fixed); cout << setprecision(8) << setw(indent) << "" << "ENTERING EXPONENTIATE ROUTINE WITH POWER = ” << power << endl; if (power == 0) result = 1.0; else if (power > 0) { indent++; result = base * exponentiate(base, power - 1); } else { indent++; result = exponentiate(base, power + 1) / base; } cout << setw(indent) << "" << "EXITING EXPONENTIATE ROUTINE WITH POWER = " << power << ", " << base << '^' << power << " = " << result << endl; indent--; return result; } CS 150

  10. Exponentiation (Continued) CS 150

  11. Recursion Example #3: Logarithm ///////////////////////////////////////////////////////////////////////////////// // Program file: logarithm.cpp // // This program queries the user for a value and a base, then uses a recursive // // function to calculate the value of the logarithm of the value to the base. // ///////////////////////////////////////////////////////////////////////////////// #include <iostream> #include <iomanip> #include <cmath> using namespace std; void queryUser(double &value, double &base); int myLog(double value, double base); // Main asks the user for a value, calls recursive log, and outputs result. // void main() { double value, base; char yORn; cout.setf(ios::fixed); cout << "Would you like to put a log on the fire? (Enter Y or N) "; cin >> yORn; while ((yORn == 'y') || (yORn == 'Y')) { queryUser(value, base); cout << "Approximate log: " << myLog(value, base) << endl << "Real log: " << log(value)/log(base) << endl << endl; cout << "Would you like to put another log on the fire? (Enter Y or N) "; cin >> yORn; } } CS 150

  12. Logarithm (Continued) // Function queryUser asks the user for positive values for // // both the floating-point value and the logarithmic base. // void queryUser(double &value, double &base) { do { cout << "Enter a positive floating-point value: "; cin >> value; } while (value <= 0.0F); do { cout << "Enter a floating-point base (greater than one): "; cin >> base; } while (base <= 1.0F); } // Function log recursively calculates the integer value of taking the // // logarithm (to the parameterized base) of the parameterized value. // int myLog(double value, double base) { int result; if ((value > 1/base) && (value < base)) result = 0; else if (value <= 1/base) result = myLog(value*base, base) - 1; else result = myLog(value/base, base) + 1; return result; } CS 150

  13. Logarithm (Continued) CS 150

  14. Given n objects, how many different sets of size k can be selected? This problem can be solved by solving two slightly smaller problems and summing the results (sounds pretty recursive!): Problem 1: Assuming that the first object is selected, how many size k-1 sets can be selected from the remaining n-1 objects? Problem 2: Assuming that the first object is not selected, how many size k sets can be selected from the remaining n-1 objects? Recursion Example #4: Combination CS 150

  15. Combination (Continued) ///////////////////////////////////////////////////////////////////// // Program file: combination.cpp // // This program queries the user for a set size and a subset size, // // and then recursively computes the number of different subsets // // of the appropriate size that could be selected from the set. // ///////////////////////////////////////////////////////////////////// #include <iostream> using namespace std; int computeCombo(int setSize, int subsetSize); // Main asks the user for the set & subset sizes, calls the // // function producing the combination, and outputs the result. // void main() { int sizeOfCollection; int sizeOfSelection; cout << "How many objects in the master collection? "; cin >> sizeOfCollection; cout << "How many objects in a single selection? "; cin >> sizeOfSelection; cout << endl << endl; cout << "FOR " << sizeOfCollection << " FANCY OBJECTS COLLECTED" << endl << "AND " << sizeOfSelection << " LUCKY CHOICES SELECTED," << endl << "THERE\'S " << computeCombo(sizeOfCollection, sizeOfSelection) << " DIFFERENT SUBSETS" << endl << "BUT EACH HAS " << sizeOfCollection-sizeOfSelection << " ANGRY UPSETS" << endl << "\'CAUSE THE REST OF THE SAPS ARE REJECTED!" << endl << endl; } CS 150

  16. Combination (Continued) ///////////////////////////////////////////////////////////// // Function computeCombo recursively calculates the number // // of different combinations of size subsetSize that can // // be obtained from a collection of size setSize. // ///////////////////////////////////////////////////////////// int computeCombo(int setSize, int subsetSize) { if ((subsetSize == 0) || (subsetSize == setSize)) return 1; if (subsetSize > setSize) return 0; return (computeCombo(setSize-1, subsetSize-1) + computeCombo(setSize-1, subsetSize)); } CS 150

  17. Recursion Example #5: Binary Search While it’s a lot easier to write a program that searches a sorted list by merely looping through the whole list (i.e., a sequential, or linear, search), it’s not exactly an efficient way of getting the job done. A more efficient approach is to use a “binary search”: Look at the middle element of the list. If that’s the value you seek, then you’re done. If it’s not, then it’s either larger or smaller than the value you seek. Since the list is sorted, you can just proceed with either the first half of the list (if the middle value was larger) or the second half (if the middle value was smaller). In either case, you’ve cut the “size” of the problem in half. That’s recursion! // Library header file: boolean.h #ifndef BOOL_H #undef TRUE #undef FALSE const int TRUE = 1; const int FALSE = 0; typedef int boolean; #define BOOL_H #endif Let’s begin by creating our own boolean type, to make our code easier to read. Just make sure to include this homemade header file in the program, and to add it to the project when you try to build the executable file. CS 150

  18. Binary Search (Continued) //////////////////////////////////////////////////////////// // Program file: binarySearch.cpp // // This program sets up a sorted list of integers, and // // then allows the user to interactively search the // // list for values by means of a recursive binary search. // //////////////////////////////////////////////////////////// #include <iostream> #include <cstdlib> #include <ctime> #include "boolean.h" using namespace std; const LIST_SIZE = 100; const HI_RAND_INT = 32767; void generateList(int list[]); int randomValue(int lowerBound, int upperBound); boolean binSearch(const int list[], int firstIndex, int lastIndex, int soughtValue, int &correctIndex); CS 150

  19. Binary Search (Continued) /////////////////////////////////////////////////////////// // Main sets up the sorted list of integers, and then // // repeatedly asks the user for the for values to be // // found (or not found) via the recursive binary search. // /////////////////////////////////////////////////////////// void main() { int sortedList[LIST_SIZE]; int valueToFind; int location; generateList(sortedList); cout << "RECURSIVE BINARY SEARCH TEST" << endl << endl; cout << "Enter a value to be sought in the list (use a negative value to quit): "; cin >> valueToFind; while (valueToFind > 0) { if (binSearch(sortedList, 0, LIST_SIZE-1, valueToFind, location)) cout << "Value " << valueToFind << " was found at index " << location << endl << endl; else cout << "Value " << valueToFind << " was not found in the list" << endl << endl; cout << "Enter another value for the search (use a negative value to quit): "; cin >> valueToFind; } cout << endl << endl; return; } CS 150

  20. Binary Search (Continued) ////////////////////////////////////////////////////////// // Function generateList fills an integer array with // // values in such a way that the array element at index // // i will contain some value between 10*i and 10*i+9. // ////////////////////////////////////////////////////////// void generateList(int list[]) { for (int i = 0; i < LIST_SIZE; i++) list[i] = i*10 + randomValue(0,9); return; } ////////////////////////////////////////////////////////////// // Function randomValue generates a pseudorandom integer in // // the range between lowerBound and upperBound (inclusive). // ////////////////////////////////////////////////////////////// int randomValue(int lowerBound, int upperBound) { static boolean firstTimeHere = TRUE; long int randomNumberSeed; if (firstTimeHere) { // The first time this function is called, time(&randomNumberSeed); // use the current system time to seed the srand(randomNumberSeed); // random number generator, avoiding identical firstTimeHere = FALSE; // results each time the program is run. } return int((upperBound-lowerBound+1)*(float(rand())/HI_RAND_INT) + lowerBound); } CS 150

  21. Binary Search (Continued) ////////////////////////////////////////////////////////////////////// // Function binSearch recursively examines the integer array list // // (assumed to already be sorted) for soughtValue. If it finds it, // // it places the index of its location in the array in parameter // // correctIndex and terminates. The only other termination // // condition occurs when the search is completely unsuccessful. // ////////////////////////////////////////////////////////////////////// boolean binSearch(const int list[], int firstIndex, int lastIndex, int soughtValue, int &correctIndex) { int middleIndex = (firstIndex + lastIndex) / 2; if (lastIndex < firstIndex) return FALSE; else if (list[middleIndex] == soughtValue) { correctIndex = middleIndex; return TRUE; } else if (list[middleIndex] < soughtValue) return binSearch(list, middleIndex+1, lastIndex, soughtValue, correctIndex); else return binSearch(list, firstIndex, middleIndex-1, soughtValue, correctIndex); } CS 150

  22. Binary Search (Continued) CS 150

  23. Recursion Example #6: Maze Solving /////////////////////////////////////////////////////////////////////////////// // This program uses recursion to traverse a maze in the form of a character // // matrix, finding the path through the maze, and marking it with asterisks. // /////////////////////////////////////////////////////////////////////////////// #include <iostream> #include <fstream> #include "boolean.h" using namespace std; const int MATRIX_SIDE = 21; enum direction {north, east, south, west}; void getMaze(char matrix[MATRIX_SIDE][MATRIX_SIDE], int &startRow, int &startCol, int &destRow, int &destCol); void solveMaze(char matrix[MATRIX_SIDE][MATRIX_SIDE], int startRow, int startCol, int destRow, int destCol); boolean proceed(char matrix[MATRIX_SIDE][MATRIX_SIDE], direction startDirection, int startRow, int startCol, int destRow, int destCol); void printMatrix(char matrix[MATRIX_SIDE][MATRIX_SIDE]); // Function main retrieves, solves, outputs the maze. // void main() { char matrix[MATRIX_SIDE][MATRIX_SIDE]; int startRow, startCol; int destRow, destCol; getMaze(matrix,startRow, startCol, destRow,destCol); solveMaze(matrix,startRow,startCol,destRow,destCol); printMatrix(matrix); } CS 150

  24. Maze Solving (Continued) ///////////////////////////////////////////////////////////////////////////////// // Function getMaze retrieves the maze matrix from a specific input file, // // assuming that it is size MATRIX_SIDE x MATRIX_SIDE, and that it is stored // // as MATRIX_SIDE lines of MATRIX_SIDE characters. The four function // // parameters will be assigned the row and column numbers of the entrance and // // exit to the maze (assuming that the entrance is either on the left side or // // the top of the matrix, and the exit is on the side opposite the entrance). // ///////////////////////////////////////////////////////////////////////////////// void getMaze(char matrix[MATRIX_SIDE][MATRIX_SIDE], int &startRow, int &startCol, int &destRow, int &destCol) { int i, j; ifstream sourceFile; char nextChar; sourceFile.open("C:\\TEMP\\maze"); for (i = 0; i < MATRIX_SIDE; i++) { for (j = 0; j < MATRIX_SIDE; j++) { sourceFile.get(nextChar); while (nextChar == '\n') sourceFile.get(nextChar); matrix[i][j] = nextChar; } } CS 150

  25. Maze Solving (Continued) for (i = 1; i < MATRIX_SIDE-1; i++) { if (matrix[i][0] == ' ') { startRow = i; startCol = 0; } else if (matrix[0][i] == ' ') { startRow = 0; startCol = i; } if (matrix[i][MATRIX_SIDE-1] == ' ') { destRow = i; destCol = MATRIX_SIDE-1; } else if (matrix[MATRIX_SIDE-1][i] == ' ') { destRow = MATRIX_SIDE-1; destCol = i; } } return; } CS 150

  26. Maze Solving (Continued) ////////////////////////////////////////////////////////////////////////////////// // Function solveMaze kicks off the recursion which will find (and mark) a path // // through the maze. // ////////////////////////////////////////////////////////////////////////////////// void solveMaze(char matrix[MATRIX_SIDE][MATRIX_SIDE], int startRow, int startCol, int destRow, int destCol) { if (startRow == 0) proceed(matrix,east,startRow,startCol,destRow,destCol); else proceed(matrix,south,startRow,startCol,destRow,destCol); } ////////////////////////////////////////////////////////////////////////////////// // Function proceed recursively proceeds through the maze, trying to ascertain // // the path to the exit. Parameter startDirection retains the direction from // // which the current path most recently arose, in order to ensure that no // // attempt will be made to bounce back and forth between two previously visited // // locations. // ////////////////////////////////////////////////////////////////////////////////// boolean proceed(char matrix[MATRIX_SIDE][MATRIX_SIDE], direction startDirection, int startRow, int startCol, int destRow, int destCol) { int eastPos[2]; int westPos[2]; int northPos[2]; int southPos[2]; boolean flag = FALSE; CS 150

  27. Maze Solving (Continued) if ((startRow == destRow) && (startCol == destCol)) // TERMINATION CONDITION: flag = TRUE; // DESTINATION REACHED! else if (matrix[startRow][startCol] != ' ') // TERMINATION CONDITION: flag = FALSE; // DEAD END REACHED!! else // RECURSIVE CONTINUATION { eastPos[0] = startRow; eastPos[1] = startCol + 1; westPos[0] = startRow; westPos[1] = startCol - 1; northPos[0] = startRow - 1; northPos[1] = startCol; southPos[0] = startRow + 1; southPos[1] = startCol; switch (startDirection) { case north: { flag = (proceed(matrix,east,eastPos[0],eastPos[1],destRow,destCol) || proceed(matrix,north,northPos[0],northPos[1],destRow,destCol) || proceed(matrix,west,westPos[0],westPos[1],destRow,destCol)); break; } case south: { flag = (proceed(matrix,east,eastPos[0],eastPos[1],destRow,destCol) || proceed(matrix,south,southPos[0],southPos[1],destRow,destCol) || proceed(matrix,west,westPos[0],westPos[1],destRow,destCol)); break; } CS 150

  28. Maze Solving (Continued) case east: { flag = (proceed(matrix,east,eastPos[0],eastPos[1],destRow,destCol) || proceed(matrix,north,northPos[0],northPos[1],destRow,destCol) || proceed(matrix,south,southPos[0],southPos[1],destRow,destCol)); break; } default: { flag = (proceed(matrix,south,southPos[0],southPos[1],destRow,destCol) || proceed(matrix,north,northPos[0],northPos[1],destRow,destCol) || proceed(matrix,west,westPos[0],westPos[1],destRow,destCol)); break; } } } // If flag is true, then the destination WAS // // reached via the current "start" position. // if (flag) matrix[startRow][startCol] = '*'; return flag; } CS 150

  29. Maze Solving (Continued) ///////////////////////////////////////////////////////// // Function printMatrix outputs the entire maze matrix.// ///////////////////////////////////////////////////////// void printMatrix(char matrix[MATRIX_SIDE][MATRIX_SIDE]) { for (int row = 0; row < MATRIX_SIDE; row++) { for (int col = 0; col < MATRIX_SIDE; col++) cout << matrix[row][col]; cout << endl; } cout << endl; return; } CS 150

  30. Maze Solving (Continued) Sample maze (in file C:\TEMP\maze): +-+-+-+-+-+-+-+-+-+-+ | | | | | | + +-+-+ + + + +-+ + + | | | | | + +-+ + +-+-+-+-+-+-+ | | +-+-+ +-+-+-+-+-+-+ + | | | | | + +-+ +-+-+ + + +-+-+ | | | | | | +-+ +-+-+ +-+-+ +-+-+ | | | | | | | + + + +-+-+ + + +-+ + | | | | +-+-+-+-+ +-+-+ +-+-+ | | | | | | + + +-+ +-+ + + + +-+ | | | | | + +-+ + +-+ + +-+ + + | | | | | | +-+-+-+-+-+-+-+-+-+-+ Results of running program on sample maze: CS 150

  31. Recursion vs. Iteration Note that in several of our examples, it would have been just as easy to implement the algorithms via iteration (i.e., looping) as it was to implement them with recursion. In fact, the use of recursion for these examples is rather wasteful, forcing the operating system to do extra work and taking the risk that a stack overflow will occur. When To Use Recursion Instead Of Iteration When a straightforward iterative solution cannot be found. CS 150

  32. The Inefficiency of Recursion One of the big drawbacks to using recursion is the inherent inefficiency of many recursive algorithms. For instance, our maze solving routine frequently revisits coordinates that have already been determined to be dead ends! On the other hand, some recursive algorithms (e.g., binary search) are vast improvements over alternative solutions. How To Measure The Efficiency Of A Recursive Algorithm Study Math 224 real hard, and then take CS 240 and 340! CS 150