Unformatted text preview: Lecture 14 Lect re 14 Midterm review
Z. Morley Mao [email protected] Monday March 3rd, 2008
1 Midt Midterm reminder: i d Administrivia March 6, Thursday 7PM8:30PM. No lecture on March 5, Wed. l h Email me ([email protected]) if you cannot make it. People taking alternate midterm should have l k l d h ld h received email from me Many office hours ffi h James: today 4pm 10pm (SHAPIRO BASEMENT) Alan: today 1:30 4 pm CSE West Morley: Tuesday 10noon 4629 CSE Scott: Tuesday 35PM CSE West
2 Material covered by the midterm P j 1 dP j 2 Project 1 and Project 2 All lecture material up to and including lecture 9 on exceptions Key topics (no particular order) y p ( p ) Arrays, pointers Cstrings C st gs Recursions, trees, lists Pass by reference by value Pass by reference, by value Function pointers Exceptions Testing 3 Sample midterm #5 Recursive String Processing Mountain word: its characters are strictly Mountain word: its characters are strictly increasing up until the middle character and strictly decreasing afterwards: strictly decreasing afterwards: E.g., house Write a tail recursive function isMountain Write a tailrecursive function isMountain, taking in any Cstring of zero or more lower case letters. case letters 4 1. List and tail recursion Given a list_t, write a tailrecursive function List_t every_other(list_t list) Returns a list containing the 1st, 3rd, 5th, etc. elements of the original list in the order they appear there. Solution: uses a helper function, need two extra parameters, a list that holds the results of intermediate computations and a boolean to intermediate computations and a boolean to represent whether to keep the current first element.
5 1. List and tail recursion 1. List and tail recursion
list_t every_other(list_t list) { return every_other_h(list, list_make(), true); return every other h(list list make() true); } list_t every_other_h(list_t list, list_t so_far, bool odd_elt) { li t t th h(li t t li t li t t f b l dd lt) { if(list_isEmpty(list)) return(so_far); if(odd_elt) f( l) so_far = append(so_far, list_make(list_first(list), list_make())); return every_other_h(list_rest(list), so_far, !odd_elt); }
6 2. Trees 2. Trees Given a tree t t write a recursive function Given a tree_t t, write a recursive function that returns true if and only if there is a path from the root of t to a leaf node that does from the root of t to a leaf node that does NOT contain 0. Define an empty tree to have such a path Define an empty tree to have such a path. 7 Solution to nonzeropath(tree_t t)
bool nonzeroPath (tree_t t) { bool nonzeroPath (tree t t) { if(tree_isEmpty()) return true; if(tree_elt(t) == 0) return false; if(tree elt(t) == 0) return false; return (nonzeroPath(tree_left(t))  nonzeropath(tree_right(t))); nonzeropath(tree right(t))); } This solution is buggy because for any tree that This solution is buggy, because for any tree that contains a path reaching a nonleaf node with one child, as long as that path contains no zeros, it will child, as long as that path contains no zeros, it will return true! E.g., for the tree to the right, it should return false, But, the above function will return true, because 2's Righttree is empty and satisfies the base case.
2 0
8 1 Improved solution
bool nonzeroPath(tree_t t) { if(tree_isEmpty(t)) return true; if(tree isEmpty(t)) return true if(tree_elt(t) == 0) return false; bool l false, r false; bool l=false r=false; //do not perform recursive call unless the child trees are non // empty if(!tree_isEmpty(tree_left(t))) l = nonzeroPath(tree_left(t)); if(!tree_isEmpty(tree_right(t))) r = nonzeroPath(tree_right(t)); return (l  r); t (l  ) } 9 3. Function pointers
double f(int a, int size, int (*fn) (int)) { ( , , ( ) ( )) { int i; double result = 0; ; for(i=0; i<size; i++) result += fn(a[i]); result = result / (double) size; return result; } Give a a function such that a pointer to that function is passed to f, f will compute:
1. average numbers in a 2. Average of squares of numbers in a, 3. Fraction of numbers in a that are greater than 3 10 4. exceptions 4. exceptions Create a program that takes from input two Create a program that takes from input two double numbers: years and cost, outputs the product of the two. product of the two If the input year is negative, throws an exception. exception If the input cost is not an integer, throws an exception. i The two exceptions must be handled separately.
11 struct NegativeYears {}; struct FractionalYears { double k; }; double f (double y, double c) { NegativeYears a; FractionalYears b; F i lY b if(y < 0 ) throw a; if(floor(y) != y) { if(floor(y) != y) { b.k=floor(y); throw b; ; } return y*c; } double years, cost; cout << "years? " << endl; cin >> years; cout << "cost? " << endl; cin >> cost; i try { cout << "year times cost: " << << year times cost: << f(years, cost) << endl; } catch(NegativeYears a) { cout << "negative years!" << endl; } catch(FractionalYears b) { cout << " t << "year (rounded) times cost: ( d d) ti t " << f(b.k, cost) << endl; 12 } 5. structs 5. structs Create a program that takes from command Create a program that takes from command line three numbers: area code, prefix, suffix of a phone number, e.g., ./a.out 313 764 0100 a phone number e g /a out 313 764 0100 First print out the old phone number If h If the prefix is greater than or equal to 500 fi i h l 500 and area code is 313, changes the area code to 734. 734 Print out the new phone number
13 Solution
struct PhoneNumber { int area_code; int i t prefix; fi int suffix; }; void print_number(PhoneNumber n) { cout << "(" << n.area_code << ")" << n.prefix << "" << n.suffix << endl; } void new_area_code(PhoneNumber &np) { if( (np.prefix >=500) && (np.area_code==313)) { np.area_code=734; np area code=734; } }
int main (int argc, char ** argv) { if(argv>=3) { PhoneNumber n; n.area_code=atoi(argv[1]); n.prefix=atoi(argv[2]); n.suffix=atoi(argv[3]); n s ffi atoi(arg [3]) print_number(n); new_area_code(n); _ _ ( ) print_number(n); } } 14 6. Destructive reverse 6. Destructive reverse Implement the reverse function: Implement the reverse function:
void reverse (char *s) //REQUIRES: s is a Cstring //REQUIRES: s is a C string //MODIFIES: the string contained in s //EFFECTS: reverses s in place. For example: the //EFFECTS i l F l th // reverse of "midterm" is "mretdim" Your solution must be iterative, and must use l b pointers (not array indexing) to traverse the string s.
15 Destructive reverse Destructive reverse Your solution must be recursive and must use Your solution must be recursive, and must use pointers (not array indexing) to traverse the string s. string s 16 Solution (iterative)
void reverse (char *s) { char *p=s; char c; while(*p) { p++; } p; while(s<p) { c = *s; *s=*p; *p = c; s++; p; } }
17 Solution (recursive)
void revHelp(char *s, char *p) { if(p>s) { char c = *s; *s = *p; *p = c; revHelp(s+1, p1); p( , p ); } } char *lastChar(char *s) { if(!*s) return s1; else return lastChar(s 1); else return lastChar(s+1); } void reverse (char *s) { id ( h * ){ revHelp(s, lastChar(s)); } 18 7. Trees Write two recursive functions on trees, You must use function pointers in some way.
int tree_max(tree_t t)
//EFFECTS: returns the largest element in t if it is not empty, // h l l f //throws 0 otherwise. int tree_min(tree_t t) ( )
//EFFECTS: returns the smallest element in t if it is not empty, //throws 0 otherwise. In writing your solution you may assume the presence of the In writing your solution, you may assume the presence of the following global constants and functions: const int INT_MIN; // smallest possible integer const int INT_MAX; // largest possible integer int min3(int a, int b, int c); //EFFECTS: returns the smallest of a,b,c int max3(int a, int b, int c); //EFFECTS: returns the largest of a,b,c int max3(int a int b int c); //EFFECTS: returns the largest of a b c int min2(int a, int b); //EFFECTS: returns the smaller of a,b 19 int max2(int a, int b); //EFFECTS: returns the larger of a,b Solution
int tree_help(tree_t t, int (*comp) (int,int,int), int base) { if(tree_isEmpty(t)) return base; else return (comp(tree_elt(t), tree_help(tree_left(t), comp, base), p( g ( ), p, ))); tree_help(tree_right(t), comp, base))); } //EFFECTS: returns the largest element in t if it is not empty, //throws the empty tree otherwise. //throws the empty tree otherwise int tree_max(tree_t t) { if(tree_isEmpty(t)) throw 0; throw 0 return tree_help(t, max3, INT_MIN); } //EFFECTS: returns the smallest element in t if it is not empty, //throws the empty tree otherwise. int tree_min(tree_t t) { if(tree_isEmpty(t)) throw 0; return tree_help(t, min3, INT_MAX); 20 } A chained hash table is defined as a global array of A chained hash table is defined as a global array of lists:
const int TABLE_SIZE = 100; const int TABLE SIZE = 100; list_t table[TABLE_SIZE]; 8. Chained Hash Tables list t holds integers, so the table holds integers. list_t holds integers, so the table holds integers. Each integer is associated with a key, from 0 to TABLE_SIZE1. When an integer is inserted, it is g , associated with a key and placed on the list with that key. Integers appear in their associated list in no particular order. Define rekey operation: an element is given a new key: it is moved from an old list to a new list in the k df ld l l h table. 21 void rekey (int element, int oldKey, int newKey) //REQUIRES: oldKey, newKey from 0 ... TABLE_SIZE 1, inclusive //REQUIRES: oldKey, newKey from 0 ... TABLE SIZE1, inclusive //EFFECTS: changes key of element from oldKey to newKey // if element is not in the list, throw int element as an exception You may assume that any particiular integer appears in the table at most once. However a key may have zero or more integers H k h i associated with it. So, each list may contain any number of integer elements. You may use iteration or tail recursion. 22 void rekey(int element, int oldKey, int newKey) { list_t l = table[oldKey]; // Shadow list Initialized ; // bool found = false; // Mechanism to remember if found table[oldKey] = list_make(); // Zero old table while (!list_isEmpty(l)) { // Termination condition if (list_first(l) != element) {// Check for element if (list first(l) != element) {// Check for element // If not element, put back table[oldKey] = list_make(list_first(l), table[oldKey]); table[oldKe ]) } else { // If the element, move it table[newKey] = list_make(element, table[newKey]); found = true; } l = list_rest(l); // Advance list } if (!found) { throw element; // Throws exception } 23 } ...
View
Full
Document
 Winter '08
 Phillips

Click to edit the document details