500 likes | 526 Views
Lecture 5: More Recursion. EXAMPLES OF RECURSION • Towers of Hanoi • Writing Linked Lists Backwards • Recursive Insert • 8 Queens • Recognizing Simple Languages • Prefix Expressions • Conversion Prefix to Postfix. 2.
E N D
EXAMPLES OF RECURSION • Towers of Hanoi • Writing Linked Lists Backwards • Recursive Insert • 8 Queens • Recognizing Simple Languages • Prefix Expressions • Conversion Prefix to Postfix 2
How do we transfer all disks from A to C, with the following limitations: 1) Only one disk at a time may be moved. 2) A larger disk may never lie on a smaller disk. The solution is simple and recursive: Basic idea: 1) Transfer recursively all but the largest disk from A to the temporary peg B. 2) Transfer the largest disk from A to C. 3) Transfer recursively all disks from B to C. A B C 3
NOTE: While you are transferring n-1 disks from A to B, you are using C as a “temporary storage”. While you are transferring n-1 disks from B to C, you are using A as a temporary storage. That’s it. It is that simple. void tow (int cnt, char src, char dst, char spr) { if (cnt = = 1) cout << src << “ --> “ << dst << endl; else { tow (cnt-1, src, spr, dst); tow (1, src, dst, spr); tow (cnt-1, spr, dst, src); } } 4
EXAMPLE: NOTE: This would work with 3 pegs, even if there are 4, 5, 6, 7, ... disks! (the pegs just have to be higher. 8-) :-) ). The solution is completely general. 5
Display the String • You want to write the characters in the string in the order in which they appear in the linked list: struct str { char data; struct str *next; }; void writeString(struct str *ptr) { if (ptr != NULL) { cout << ptr->data << endl; writeString(ptr->next); } } 6
Writing Linked Lists Backward (recursively) Writing this program is very hard iteratively. It’s very easy recursively: ********************************************************** struct str { char data; struct str *next; }; void writeback(struct str *ptr) { if (ptr != NULL) { writeback (ptr->next); cout << ptr->data << endl; } } 7
head T C A NULL Assume that data is now a single character! Writeback(head) str str str str First call 2nd call 3rd call Last call 8
Strip a way first character writeBackward2(char [] s) { cout << “Enter writBackward2 with string: “ << s<< endl; if (the string is empty) //Do nothing – this is the base case else { writedBackward2 (s minus its character ); // calling point cout << “About to write first character of string:” << s << endl; write the first character of s } cout << “leave writeBackward2 with string: “ << s << endl; } 9
Insert Revisited We will now redo “insert into sorted linked list”. This time recursively. It turns out that this is simpler than iterative insert. This eliminates the need for trailing pointer and a special case for inserting into the beginning of the list void Insert (struct node *L, struct node *pre, int X) { if ((L == NULL) || (X < L->data)) { struct node *p = new node; p ->data = X; p->next = L; L = p; pre->next=p; } else Insert (L->next, L, X); } 10
Example head 12 4 8 x 10 Example head 12 4 8 x 2 11
Backtracking • Backtracking • A strategy for guessing at a solution and backing up when an impasse is reached • Recursion and backtracking can be combined to solve problems • Eight-Queens Problem • Place eight queens on the chessboard so that no queen can attack any other queen
The Eight Queens Problem • One strategy: guess at a solution • There are 4,426,165,368 ways to arrange 8 queens on a chessboard of 64 squares • An observation that eliminates many arrangements from consideration • No queen can reside in a row or a column that contains another queen • Now: only 40,320 (8!) arrangements of queens to be checked for attacks along diagonals
The Eight Queens Problem Figure 5-1 (a) Five queens that cannot attack each other, but that can attack all of column 6; (b) backtracking to column 5 to try another square for the queen; (c) backtracking to column 4 to try another square for the queen and then considering column 5 again
The Eight Queens Problem Figure 5-2 A solution to the Eight Queens problem • Providing organization for the guessing strategy • Place queens one column at a time • If you reach an impasse, backtrack to the previous column
The Eight Queens Problem • A recursive algorithm that places a queen in a column • Base case • If there are no more columns to consider • You are finished • Recursive step • If you successfully place a queen in the current column • Consider the next column • If you cannot place a queen in the current column • You need to backtrack
Backtracking • Backtracking is kind of solving a problem by trial and error. However, it is a well organized trial and error. We make sure that we never try the same thing twice. • We also make sure that if the problem is finite we will eventually try all possibilities (assuming there is enough computing power to try all possibilities). 17
The n Queens problem: • Given is a board of n by n squares. • Is it possible to place n queens (that behave exactly like chess queens) on this board, without having any one of them attack any other queen? • Example: 2 Queens problem is not solvable. • Example 2: The 4-queens problem is solvable: 18
Basic idea of solution: • Start with one queen in the first column, first row. • Start with another queen in the second column, first row. • Go down with the second queen until you reach a permissible situation. • Advance to the next column, first row, and do the same thing. · If you cannot find a permissible situation in one column and reach the bottom of it, then you have to go back to the previous column and move one position down there. (This is the backtracking step.) · If you reach a permissible situation in the last column of the board, then the problem is solved. · If you have to backtrack BEFORE the first column, then the problem is not solvable. 19
illegal illegal illegal illegal legal illegal I cannot go further down in row 3. I cannot go further down in row 3. I must backtrack! However, I can not go further down in column 2 either. I must backtrack one more step. 20
Q Q Q Q Q Q Q Q Q At this point I am at the end of the first column. I would have to backtrack again, but that’s impossible, so the problem is unsolvable. illegal illegal illegal backtrack Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q illegal legal illegal illegal bkt/ill ill/end 22
We will work out a successful example also: QQ++ Q+++ Q+++ Q+Q+ Q+++ Q+++ ++++ +Q++ ++++ ++++ ++Q+ ++++ ++++ ++++ +Q++ +Q++ +Q++ +QQ+ ++++ ++++ ++++ ++++ +++++ ++++ Illegal illegal legal illegal illegal illegal Q+++ Q+Q+ Q+++ Q+++ Q+++ ++++ ++++ ++Q+ ++++ ++++ +Q++ ++++ ++++ ++Q+ ++++ ++Q+ +Q++ +Q++ +Q++ +QQ+ Illegal illegal illegal illegal illegal 23
Backtrack to column 2. Then backtrack to column 1. Then go down in column 1. +Q++ 3 ++++ ++Q+ ++QQ ++Q+ ++Q+ Q+++ ill Q+++ Q+++ Q+++ Q++Q Q+++ ++++ steps ++++ ++++ ++++ ++++ +++Q ++++ +Q++ +Q++ +Q++ +Q++ +Q++ Illegal ill ill legal I placed 4 queens on a 4X4 board. Problem solved. 24
Are there other solutions? There must be, due to symmetry: We can continue the program to find this and other solutions. • The program is long and complicated. It certainly does not fit onto one screen. It moves from one row to the next row with a while loop. However, it moves from one column to the next column by recursion. This is done as follows: 25
26 void PlaceNextQueen (int Column, boardtypes &Board, boolean &Done) { .............. .............. PlaceNextQueen(Column+1, Board, Done); } Please study the program in your textbook. Good exercise: Try to write the FUNCTION IsUnderAttackwhich is used in the book, but not explained. IsUnderAttack() returns TRUE if on the board there is any queen that can attack the field in row Row and column Column. Ex5-1.cpp
Defining Languages • A language • A set of strings of symbols • Examples: English, C++ • A grammar • The rules for forming the strings in a language • Examples: English grammar, C++ syntax rules
Defining Languages • If a C++ program is one long string of characters, the language of C++ programs is defined as C++Programs = {strings w : w is a syntactically correct C++ program} • A language does not have to be a programming or a communication language • AlgebraicExpressions = {strings w : w is an algebraic expression}
The Basics of Grammars • Symbols used in grammars • x | y means x or y • x y or x • y means x followed by y • The symbol • means concatenate (append) • < word > means any instance of word that the definition defines
The Basics of Grammars • A C++ identifier begins with a letter and is followed by zero or more letters and digits • Language of C++ identifiers C++Ids = {w : w is a legal C++ identifier} • Grammar < identifier > = < letter > | < identifier > < letter > | < identifier > < digit> < letter > = a | b | … | z | A | B | …| Z | _ < digit > = 0 | 1 | … | 9
The Basics of Grammars • A recognition algorithm sees whether a given string is in the language • A recognition algorithm for a language is written more easily if the grammar is recursive
The Basics of Grammars • Recognition algorithm for the language C++ Ids bool isId(string w) { if (w is of length 1) if (w is a letter) return true; else return false; else if (the last character of w is a letter or a digit) return isId(w minus its last character); else return false ; } Ex5-2.cpp
Two Simple Languages: Palindromes • A string that reads the same from left to right as it does from right to left • Language Palindromes = {w : w reads the same left to right as right to left} • Grammar < pal > = empty string | < ch > | a < pal > a | b < pal > b | …| Z < pal > Z < ch > = a | b | … | z | A | B | … | Z
Two Simple Languages: Palindromes • Recognition algorithm bool isPal(string w) { if (w is the empty string or w is of length 1) return true; else if (w’s first and last characters are the same letter ) return isPal(w minus its first and last characters); else return false; } Ex5-2.cpp
Two Simple Languages: Strings of the Form AnBn • AnBn • The string that consists of n consecutive A’s followed by n consecutive B’s • Language L = {w : w is of the form AnBn for some n≥ 0} • Grammar < legal-word > = empty string | A < legal-word > B
Two Simple Languages: Strings of the form AnBn • Recognition algorithm bool isAnBn(string w) { if (the length of w is zero) return true; else if (w begins with the character A and ends with the character B) return isAnBn(w minus its first and last characters); else return false; } Ex5-2.cpp
Algebraic Expressions • Infix expressions • An operator appears between its operands • Example: a + b • Prefix expressions • An operator appears before its operands • Example: + a b • Postfix expressions • An operator appears after its operands • Example: a b +
Algebraic Expressions • To convert a fully parenthesized infix expression to a prefix form • Move each operator to the position marked by its corresponding open parenthesis • Remove the parentheses • Example • Infix expression: ( (a + b) * c ) • Prefix expression: * + a b c
Algebraic Expressions • To convert a fully parenthesized infix expression to a postfix form • Move each operator to the position marked by its corresponding closing parenthesis • Remove the parentheses • Example • Infix expression: ( (a + b) * c ) • Postfix expression: a b + c *
Algebraic Expressions • Advantages of prefix and postfix expressions • No precedence rules • No association rules • No parentheses • Simple grammars • Straightforward recognition and evaluation algorithms
Prefix Expressions • Grammar < prefix > = < identifier > | < operator > < prefix > < prefix > < operator > = + | - | * | / < identifier > = a | b | … | z • A recursive recognition algorithm • Base case: One lowercase letter is a prefix exp. • Recursive: < operator > < prefix > < prefix >
Prefix Expressions • If E is a prefix expression If Y is any nonempty string of nonblanks Then E • Y cannot be prefix • Recognition algorithm bool isPre() { lastChar = endPre(0); // returns index of end return (lastChar >= 0 and lastChar == strExp.length() - 1); }
Prefix Expressions int endPre(int first) { lastChar = strExp.length() - 1 if (first < 0 or first > last) return -1; ch = strExp[first]; if (ch is an identifier) return first; else if (ch is an operator) { firstEnd = endPre(first + 1); if (firstEnd > -1) return endPre(firstEnd + 1); else return -1; } else return -1; }
Prefix Expressions • Algorithm that evaluates a prefix expression float evaluatePrefix(string & strExp) { ch = first character of expression strExp; Delete first character from strExp; if (ch is an identifier) return value of the identifier; else if (ch is an operator named op) { operand1 = evaluatePrefix(strExp); operand2 = evaluatePrefix(strExp); return operand1 op operand2 ; } } Ex5-2.cpp
Postfix Expressions • Grammar < postfix > = < identifier > | < postfix > < postfix > < operator > < operator > = + | - | * | / < identifier > = a | b | … | z • The recursive case for conversion from prefix form to postfix form postfix(exp) = postfix(prefix1) + postfix(prefix2) + <operator>
Postfix Expressions • Recursive algorithm that converts a prefix expression to postfix form void convert(string& pre, string& post) { ch = first character in pre; Delete first character in pre if (ch is a lowercase letter) post = post + ch; else { convert(pre, post); convert(pre, post); post = post + ch; } } Ex5-2.cpp
Fully Parenthesized Expressions • Fully parenthesized infix expressions • Do not require precedence rules or rules for association • But are inconvenient for programmers • Grammar < infix > = < identifier > | (< infix > < operator > < infix > ) < operator > = + | - | * | / < identifier > = a | b | … | z
Recursion and Mathematical Induction • Recursion and mathematical induction • Both use a base case to solve a problem • Both solve smaller problems of the same type to derive a solution • Induction can be used to • Prove properties about recursive algorithms • Prove that a recursive algorithm performs a certain amount of work
Summary • Backtracking is a solution strategy that involves both recursion and a sequence of guesses that ultimately lead to a solution • A language is a set of strings of symbols • A grammar is a device for defining a language • A recognition algorithm for a language can often be based directly on the grammar of the language • Grammars are frequently recursive
Summary • Different languages of algebraic expressions have their relative advantages and disadvantages • Prefix: simple grammar, hard to use • Postfix : simple grammar, hard to use • Infix: involved grammar, easy to use • Induction can be used to prove properties about a recursive algorithm