Presentation is loading. Please wait.

Presentation is loading. Please wait.

Announcements HW3 grades will be announced this week

Similar presentations


Presentation on theme: "Announcements HW3 grades will be announced this week"— Presentation transcript:

1 Announcements HW3 grades will be announced this week
HW4 is due this week Final exam on August 25, 2010, Wednesday at 09:00 Duration is about 140 minutes (+/- 10 minutes) Comprehensive but last topics will have more weight 2 pages of cheat notes are allowed I will send classrooms later via Extra Recitations will be held next week before the final I will make an announcement later about the final recitation times.

2 Recursion, Scope, Function Templates
Not so related to each other Chapter 10 and partially 11 10.1, 10.3 (skip ), 10.4, 11.2

3 Global Variables (10.4.1) Have you ever needed a variable that can be referred in all functions? Global variables are defined outside of function bodies and can be used in all functions but in that cpp file, cannot be used in other cpp files Global definitions can be shadowed by local definition if a global variable is redefined in a function, in that function local one is used, global one cannot be reached See globaldemo.cpp (not in the book) Do not use global variables in your homework, but you have to know what they are!

4 Hidden Identifiers (10.4.2) These are Identifiers defined in inner compound blocks An identifier defined in a block can be used only in this block See scope.cpp as an example Same identifier names can be used in nested blocks shadow rules apply When an identifier is used, the nearest definition in the same or outer compound blocks is referred better to see in an example (scope.cpp) let’s trace that program Global identifiers and identifiers defined in compound blocks can be used together in more complex cases See this week recitations for an example

5 Function Templates (11.2) We have seen Function Overloading before
different functions with same name are possible but the parameters must be different so the compiler can differentiate void dosomething (int a, int b); void dosomething (int a); Think about a particular sort algorithm for different vector item types (comparable item types), we will need different functions the only difference is the item type overloading works but requires different functions that are almost the same except the item type Isn’t there a way to make the type parameter? YES, function templates

6 Function Templates In main An identifier template <class Type>
void Print(const tvector<Type> & list, int first) // post: list[first]..list[list.size()-1] printed, one per line { int k; for(k=first; k <= list.size()-1; k++) cout << list[k] << endl; } In main tvector<string> wordList; tvector<int> lengthList; Print(wordList, 3); Print(lengthList, 0);

7 Function Templates Not only for vectors, but also the ordinary parameter types can be template template <class T> void myfunction (T & param) { } Templates can be used as local type, but there must be at least one such parameter too template <class TT> void dosomething (tvector<TT> & vec) TT value; Templates can be used as the return type, but there must be at least one such parameter too template <class TType> TType myfunction (const tvector<TType> & p) TType myfunction (int a) // Not valid

8 Recursion (10.1, 10.3) Recursion is an essential technique in a programming language Allows many complex problems to be solved simply Elegance and understanding in code often leads to better programs: easier to modify, extend, verify Sometimes recursion isn’t appropriate. When it performs bad, it can be very bad! need knowledge and experience in how to use it. Some programmers are “recursion” programmers, some are not Recursion is not a statement, it is a technique! The basic idea is to get help solving a problem from coworkers (clones) who work and act like you do Ask clone to solve a simpler but similar problem Use clone’s result to put together your answer looks like calling a function in itself, but should be done very carefully!

9 Print words entered, but backwards
Can use a vector, store all the words and print in reverse order Using a vector is probably the best approach, but recursion works too (see printreversed.cpp) void PrintReversed() { string word; if (cin >> word) // reading succeeded? { PrintReversed(); // print the rest reversed cout << word << endl; // then print the word } int main() PrintReversed(); return 0; The function PrintReversed reads a word, prints the word only after the clones finish printing in reverse order Each clone runs a copy of the function, and has its own word variable See the trace on the board

10 What is recursion? Not exactly calling a function in itself
although it seems like this Recursion is calling a “copy” of a function in itself clone All local identifiers are declared anew in a clone when execution order comes back to the caller clone, the values in that clone is used

11 Exponentiation Computing xn means multiplying n numbers
x.x.x.x.x.x ... x (n times) If you want to multiply only once, you ask a clone to multiply the rest (xn = x.xn-1) clone recursively asks other clones the same until no more multiplications each clone collects the results returned, do its multiplication and returns the result See the trace on board double Power(double x, int n) // post: returns x^n { if (n == 0) return 1.0; } return x * Power(x, n-1);

12 General Rules of Recursion
Although we don’t use while, for statements, there is a kind of loop here if you are not careful enough, you may end up infinite recursion Recursive functions have two main parts There is a base case, sometimes called the exit case, which does not make a recursive call printreversed: having no more input exponentiation: having a power of zero All other cases make a recursive call, most of the time with some parameter that moves towards the base case Ensure that sequence of calls eventually reaches the base case we generally use if - else statements to check the base case not a rule, but a loop statement is generally not used in a recursive function

13 Faster exponentiation
double Power(double a, int n) // post: returns a^n { if (n == 0) { return 1.0; } double semi = Power(a, n/2); if (n % 2 == 0) { return (semi * semi); return (a * semi * semi); Study the code in

14 Classic examples of recursion
For some reason, computer science uses these examples: Factorial: we have seen the loop version, now we will see the recursive one Fibonacci numbers: Classic example of bad recursion (will see) Towers of Hanoi (will not cover) N disks on one of three pegs, transfer all disks to another peg, never put a disk on a smaller one, only on larger Peg# # #3

15 Factorial (recursive)
BigInt RecFactorial(int num) { if (0 == num) return 1; } else return num * RecFactorial(num - 1); See (facttest.cpp) to determine which version (iterative or recursive) performs better? almost the same

16 Fibonacci Numbers 1, 1, 2, 3, 5, 8, 13, 21, … Find nth fibonacci number see fibtest.cpp for both recursive and iterative functions and their timings Recursion performs very bad for fibonacci numbers reasons in the next slide

17 Fibonacci: Don’t do this recursively
5 int RecFib(int n) // precondition: 0 <= n // postcondition: returns // the n-th Fibonacci number { if (0 == n || 1 == n) return 1; } else return RecFib(n-1) + RecFib(n-2); Too many unnecessary calls to calculate the same values How many for 1? How many for 2, 3? 4 3 3 2 2 1 2 1 1 1 1

18 What’s better: recursion/iteration?
There’s no single answer, many factors contribute Ease of developing code Efficiency In some examples, like Fibonacci numbers, recursive solution does extra work, we’d like to avoid the extra work Iterative solution is efficient The recursive inefficiency of “extra work” can be fixed if we remember intermediate solutions: static variables Static variable: maintain value over all function calls Ordinary local variables constructed each time function called but remembers the value from previous call initialized only once in the first function call

19 Fixing recursive Fibonacci
int RecFibFixed(int n) // precondition: 0 <= n <= 30 // postcondition: returns the n-th Fibonacci number { static tvector<int> storage(31,0); if (0 == n || 1 == n) return 1; else if (storage[n] != 0) return storage[n]; else storage[n] = RecFibFixed(n-1) + RecFibFixed(n-2); return storage[n]; } Storage keeps the Fibonacci numbers calculated so far, so that when we need a previously calculated Fibonacci number, we do not need to calculate it over and over again. Static variables initialized when the function is called for the first time Maintain values over calls, not reset or re-initialized in the declaration line but its value may change after the declaration line.

20 Recursive Binary Search
Binary search is good for searching an entry in sorted arrays/vectors We have seen the iterative approach before Now recursive solution if low is larger than high not found if mid-element is the searched one return mid (found) if searched element is higher than the mid element search the upper half by calling the clone for the upper half if searched element is lower than the mid element search the lower half by calling the clone for the lower half Need to add low and high as parameters to the function

21 Recursive Binary Search
int bsearchrec(const tvector<string>& list, const string& key, int low, int high) // precondition: list.size() == # elements in list // postcondition: returns index of key in list, -1 if key not found { int mid; // middle of current range if (low > high) return -1; //not found else { mid = (low + high)/2; if (list[mid] == key) // found key { return mid; } else if (list[mid] < key) // key in upper half { return bsearchrec(list, key, mid+1, high); else // key in lower half { return bsearchrec(list, key, low, mid-1);


Download ppt "Announcements HW3 grades will be announced this week"

Similar presentations


Ads by Google