ดาวน์โหลดงานนำเสนอ
งานนำเสนอกำลังจะดาวน์โหลด โปรดรอ
ได้พิมพ์โดยBryan Briggs ได้เปลี่ยน 6 ปีที่แล้ว
1
Recursion Lecturers : Boontee Kruatrachue Room no Kritawan Siriboon Room no. 913 Text : Data Structures & Algorithm Analysis in C, C++,… Mark Allen Weiss, Addison Wesley
2
Recursion What is recursion?
Why recursion ? When would I use recursion?
3
Solving Algorithm Problem : Eat your Meal
There are 2 ways to look at the problem. Iteration : Repeat 1 bite until done. Recursion.
4
Recursion Problem : Eat your Meal
Recursion : by breaking down a problem into a smaller versions of itself and then be able to build up to a solution to the entire problem. EatMeal (big) : EatMeal (smaller) EatMeal (bite n) : EatMeal (n-1) + eat 1 bite. /or eat 1 bite + EatMeal (n-1). Recursion is the process of defining a problem (or the solution to a problem) in terms of (a simpler version of) itself.
5
Base Case & Backtracking
EatMeal (6) : EatMeal (5) + eat 1 bite . Recursively call EatMeal (5) : EatMeal (4) + eat 1 bite. Recursively call EatMeal (4) : EatMeal (3) + eat 1 bite. Recursively call
6
Base Case & Backtracking
Recursively call Keep calling recursion ==> infinite loop. Must stop somewhere ! ==> base case no recursively call EatMeal (3) : EatMeal (2) + eat 1 bite . Recursively call Backtracking Backtracking to the previous stop EatMeal (2) : EatMeal (1) + eat 1 bite. Backtracking Recursively call Base case (no recursively call) EatMeal (1) : eat 1 bite.
7
Base Case & Backtracking
EatMeal (6) : EatMeal (5) + eat 1 bite . Backtracking Recursively call Done ! EatMeal (5) : EatMeal (4) + eat 1 bite. Backtracking Recursively call EatMeal (4) : EatMeal (3) + eat 1 bite. Backtracking Recursively call
8
Factorial Iteration 0! = 1 1! = 1 2! = 2 * 1 3! = 3 * 2 * 1
4! = 4 * 3 * 2 * 1 5! = 5 * 4 * 3 * 2 * 1 n! = n*(n-1)*(n-2) *...*1 4! = 4 *3 *2 *1 Iterative : Repeat times i to the result. int fac (int n) //n>=0 { int result = 1; for (int i=n; i>=1; i--) result *= i; return result ; }
9
Factorial Recursion n! = 1 if n=0, n=1 //base case
Recursion is the process of defining a problem in terms of (a simpler version of) itself. 4! = 4 * 3 * 2 * 1 3! = 3 * 2 * 1 2! = 2 * 1 1! = 1 0! = 1 4! = 4 * 3! 3! = 3 * 2! 2! = 2 * 1! 1! = 1 0! = 1 n! = if n=0, n=1 //base case n! = n*(n-1) ! if n>1 //recursive case int fac (int n) { //n>=0 if (n<=1) return 1; else return n * fac(n-1); }
10
Fibonaci Sequence Iterative
1 2 3 5 8 f0 f1 f2 f3 f4 f5 f6 f7 ... 13 21 lo hi new lo hi new lo hi new lo hi new lo hi new int fib(int n) { // iterative, n>=0 int lo = 0; int hi = 1; int new; if (n==1 || n==0) return n; for( int i = 2; i<=n; i++){ new = hi + lo; lo = hi; hi = new; } return new;
11
Fibonaci Sequence Recursive
1 2 3 5 8 f0 f1 f2 f3 f4 f5 f6 f7 ... f7 = ? f7 = f6 + f5 fib(n) = //base case fib(n) = //recursive case n if n=0, n=1 fib(n-1) + fib(n-2) if n>1 int fib (int n) { // recursive, n>=0 if (n<=1) return n; else return fib(n-1) + fib(n-2); }
12
Binary Search Recursive
search for x = 17.5 1 3 4 5 17 18 31 33 2 6 7 L1 H1 M1 17 <17.5 L H2 M2 31 17.5< L3,H3 M3 17.5 < 18 search (0, 7, 17.5) H4 < L4 ret_value search (low, high, x) if (high < low) return(-1); //simple case mid = (low+high)/2; if (x==a[mid]) return(mid); //simple case else if (a[mid] < x) return search (mid+1, high, x) //recursive case else return search (low, mid-1, x) //recursive case
13
Recursive Algorithms Recursive algorithms Always have a parameter Recursive call always involves a modified version of the parameter Always have a condition on the parameter to stop the recursion
14
Stack of Recursion stack Backtracking return to the previous call
int fac (int n) //n>=0 { if (n <= 1) //base case return 1; else } // int main(){ int i = fac(4); stack fac(1) 1 1 fac(2) 1 2*1 = 2 fac(3) 2 return n * fac(n-1); 3*2 = 6 fac(4) 6 { int x; x = fac(n-1); //recursive return n * x; } n x 4*6 = 24 main() i - 24 To clearly see the process, we change the code to have x to recieve the returning value of fac( ).
15
Iteration VS Recursion
int facI (int n) //n>=0 { int result = 1; for (int i=n; i>=1; i--) result *= i; return result ; } int facR (int n) { //n>=0 if (n<=1) return 1; else return n * facR(n-1); } RunTime ? Space ?
16
Tail Recursion Tail Recursion execute recursion as the last one.
int fac (int n) { if (n<=1) return 1; else return n * fac(n-1); } Tail Recursion execute recursion as the last one. Tail recursion is very easy to write in iteration. int fib (int n) { if (n<=1) return n; else return fib(n-1) + fib(n-2); } Iteration is usually more efficient. Recursion suffers from function call overhead. Passing parameters. Pushing /Poping stack. int search(int low, int high, int x) { if (low>high) return(-1); //simple case mid = (low+high)/2; if (x==a[mid]) return(mid); //simple case else if (a[mid] < x) return search (mid+1,high,x) //recur else return search (low,mid-1,x) //recur } So, Why bother recursion?
17
When would I use recursion?
Recursion makes the most sense whenever you need iterative branching. The n-queen problem has iterative branching and uses the call stack advantage when backtracking to remember the previous conditions. The Sierpinski triangle (เชอเรอปีนสกี), 3 time recursively calls with different parameters, the tower of Hanoi, 2 time recursively calls. Recursive call Base case
18
Tower of Hanoi A B C A B C 4 2 3 1 4 2 3 1 ต้องการหยิบแผ่นดิกส์ทั้งหมดจากเสา A ไปเสา C โดยใช้เสา B ช่วย หยิบทีละแผ่น ต้องหยิบแผ่นที่อยู่ด้านบนก่อน แผ่นใหญ่ห้ามวางทับแผ่นเล็ก
19
Tower of Hanoi move 4 disks (A->C ) A B C move 3 disks (A->B)
What is the problem? move 4 disks (A->C ) A B C 4 2 3 1 What are you doing ? move 3 disks (A->B) 2 3 1 4 What are you doing ? move disk #4 from A to C 2 3 1 4 What are you doing ? move 3 disks (B->C) 4 2 3 1 Is this recursion. How ?
20
A B C Tower of Hanoi What is a Problem ? What is a Subproblem ?
Why 4 ? Change to general case ! n n-1 4 3 _____ ( big ) : ____ (smaller ) + ... move move 3 2 1 4 A B C Oh! If I move #4 to C, that’s done!
21
Tower of Hanoi A B C What is a base case ? When do we stop moving?
if (n==1) printf(“move disk n from %c to %c”, A,C); else { from, to, aux , A, C, B _____ ( n ) : ____ (n ) move move ,A, B,C printf(“move disk n from %c to %c”, A,C); move( n-1, B, C, A); } 3 2 1 4 A B C
22
Tower of Hanoi A B C void move(int n, char A, char C, char B) {
4 2 3 1 void move(int n, char A, char C, char B) { if (n == 1) cout << n << “from” << A << “to” << C; else { move(n-1, A, B, C); move(n-1, B, C, A); } 2 3 1 4 2 3 1 4 4 2 3 1
23
Recursion VS Iteration
Iteration is usually more efficient in space and runtime since recursion suffers from function call overhead ( passing parameters, pushing-poping stack). Coding iterative branching, recursion uses less coding time, more readable & understandable and easier for debugging.
24
Sierpinski Triangle The Sierpinski Triangle, also called Sierpinski Gasket and Sierpinski Sieve, is named after Waclaw Sierpinski, a Polish mathematician ( ).
25
Sierpinski Triangle The Sierpinski Triangle can be drawn by hand as follows: Start with a single triangle. This is the only triangle in this direction, all the others will be upside down. Inside this triangle, draw a smaller upside down triangle. It's corners should be exactly in the centers of the sides of the large triangle. Now, draw 3 smaller triangles in each of the 3 triangles that are pointing upwards, again with the corners in the centers of the sides of the triangles that point upwards. Now there are 9 triangles pointing upwards. In each of these 9, draw again smaller upside down triangles. In the 27 triangles pointing upwards, again draw 27 triangles pointing downwards. After infinite steps, and if all triangles pointing upwards would be filled, you have the Sierpinski Sieve. Every step, more triangles have to be drawn. This is a recursive process.
26
Sierpinski Triangle Algorithm
Splits a triangle into 4 smaller triangles, and then calls itself for 3 of the 4 smaller triangles. Sierpinski (triangle) Find the mid point of each side of the triangle Draw lines connecting the midpoints, which will form 4 smaller triangles called A, B, C and D, where D in the center. Color in (or cut out) the center triangle D. Do Sierpinski (triangle A) Do Sierpinski (triangle B) Do Sierpinski (triangle C)
27
The N Queen Problem Placing N chess queens on an N×N chessboard so that no two queens attack each other. Q Q Solution for 4 Queen problem. The expected output. Solution for 8 Queen problem. 8 x 8 board has 92 distinct solutions. 12 unique solutions (reduce redundency of symmetry (rotations & reflections)).
28
N Queen Naive Algorithm
Naive Algorithm Generate all possible configurations of queens on board and print a configuration that satisfies the given constraints. ลองใส่ Queen ทุกแบบ ถ้าไม่กินกัน พิมพ์ผลลัพธ์ while (still untried configuration){ board = next configuration; if (noAttacking(board)) print (board); }
29
Data Structure for Queens – 2D array
How can we keep queens? Q 2D array. #define N 4 int board[N,N];
30
Recursive PutQueen Algorithm
Backtracking Algorithm :ใส่ควีนทีละแถว เรีมจากแถวบนสุด ใส่แถวละตัว จะใส่ได้เมื่อไม่ถูกตัวที่ใส่ไปแล้วกิน ok? Q putQueenInRow (0,...) ok? ok? ok? Q void PutQueenInRow (int r, int board[N][N]){ for (int c=0; c<N; c++) // ใล่ใส่ไปทีละ column ทุก col. if (isSafe(board, r,c)) { // ถ้าใส่แล้วไม่ถูกกิน board[r,c] = 1; // ใส่ queen if (r==N-1){ // ถ้าใส่ queen ครบแล้ว printBoard(board); numsol++; }else PutQueenInRow (r+1,board); // ใส่ queen ในแถวถัดไป //backtracking point board[r,c] = 0; // เอา Queen ออกจาก board[r][c]) // เพื่อให้ได้ solution อื่น หรือ // หรือเพราะ queen ตัวนี้แม้ใส่ได้แต่ไม่ทำให้เกิด solution } // if (isSafe(board, r,c)) } Q Q Q Q
31
Detecting Crashes 3, 4 To put Q(r, c) , no row check (place row by row) but must check 1. col(c) free? Check this col of the row above Q[r,c] 2. up(7) free? Check up diagonal right to Q[r,c] 3. down(6) free? Check down diagonal left to Q[r,c] Queen can eat in 8 directions. bool isSafe(int board[N][N], int r, int c){ c0 c1 c2 c3 c4 c5 c6 c7 r0 u0 d0 r1 u1 d1 r2 u2 d2 r3 u3 Q (r,c) d3 r4 u4 d4 r5 u5 d5 r6 u6 d6 r7 u7 d7 d14 u8 d13 u9 d12 u10 d11 u11 d10 u12 d9 u13 d8 u14 Q while(r >= 0) if (board[--r][c]) return false; Q Q while(r < N && c>=0 ) if (board[--r][++c]) return false; while(c >= 0 && r >= 0) if (board[--r][--c]) return false; return true; }
32
Other Data Structures & Safe Checking
33
Detecting Crashes Q Queen can eat in 8 directions.
r0 u0 d0 r1 u1 d1 r2 u2 d2 r3 u3 Q d3 r4 u4 d4 r5 u5 d5 r6 u6 d6 r7 u7 d7 d14 u8 d13 u9 d12 u10 d11 u11 d10 u12 d9 u13 d8 u14 3, 4 To put Q(r, c) must check col(c) free? up(7) free? up(r+c) up(3+4) down(6) free? down(r-c+(n-1)) Since we place row by row so we don’t need to check the row.
34
Detecting Crashes Q 1, 3 To put Q(r, c) must check col(3) free?
up(4) free? up(r+c) up(1+3) down(1) free? down(r-c+(n-1))
35
Data Structure for Save Checking
C uses int to represent boolean: 0 means false. Others means true. Initialize all slots to 1. Clean board all are free. col free? How many col ? int colFree[N]; up free? upFree(r+c) int upFree[(2*N)-1]; down free? downFree(r-c+(n-1)) int downFree[(2*N)-1]; colFree 1 2 3 c0 c1 c2 c3 u0 d0 u1 d1 u2 d2 u3 d3 d6 u4 d5 u5 d4 u6 Q upFree 1 2 3 4 5 6 downFree 1 2 3 4 5 6
36
Data Structure for Queens – 1D array
Before: We keep queens in 2D array. #define N 4 int board[N,N]; Q c3 r1 Q We can use 1 dimentional array. int b [N]; b 3 row 1 2
37
Initializations #define N 8 #define D 2*N //diagonals
int numsol = 0; //number of solutions int main( ) { int b[N]; //board indice are row int colFree[N], upFree[D], downFree[D]; for (int i = 0 ; i < N ; i++ ) colFree[i]= 1; //true for (int i = 0 ; i < D ; i++ ) upFree[i]= downFree[i]= 1; //true PutQueenInRow(0,b,colFree,upFree,downFree); //put in row 0 //recursive printf("Total solutions = %d\n",numsol); return 0; } int numsol = 0; //number of solutions int b[N]; //board indice are row int colFree[N], upFree[D], downFree[D]; PutQueenInRow(0,b,colFree,upFree,downFree); //put in row 0 //recursive
38
Recursive PutQueen Q Q Q Q Q Q putQueenInRow (0,...)
void PutQueenInRow (int r,int b[],int colFree[],int upFree[],int downFree[]) { for (int c=0; c<N; c++) //for each column of this row if (colFree[c] && upFree[r+c] && downFree[r-c+N-1]){//if save b[r] = c; //put queen colFree[c] = upFree[r+c] = downFree[r-c+N-1]= 0; //not free any more if (r==N-1){ //if all queens are put printBoard(b); numsol++; }else PutQueenInRow (r+1,b,colFree,upFree,downFree); //put next Q //backtracking point colFree[c] = upFree[r+c] = downFree[r-c+N-1]= 1; //take the Queen out } // if save // for other solutions } //or if doesn’t lead to solution ok? Q ok? ok? ok? Q Q Q if (colFree[c] && upFree[r+c] && downFree[r-c+N-1]){//if save Q b[r] = c; //put queen Q colFree[c] = upFree[r+c] = downFree[r-c+N-1]= 0; //not free any more colFree[c] = upFree[r+c] = downFree[r-c+N-1]= 1; //take the Queen out
39
A B A B C Recursive Chain Is this Expression? : A * B + C
Recursive Chain : Function that indirectly calls himself from the other function(s). A B A B C E : expression T : term F : facter E = T + T | T T = F * F | F F = letter | (E) Is this Expression? : A * B + C F F F * T + T E
40
A B Forward Declaration A(formal parameters){ B(actual arguments); }
B(formal parameters){ A(actual arguments); B(formal parameters); //Forward Declaration
41
C++ E = T + T | T T = F * F | F F = letter | (E)
s1="12345" s1.length()= 5 s="ABCDE"; string s2(s,1,3); //s2 = "BCD" from s[1] 3 chars string s3(s,2,2); //s3 = "CD" from s[2] 2 chars C++ bool expression(const string& s){ //E = T+T | T size_t npos = s.find("+"); size_t len = s.length(); if (npos<0 || npos>=len) //notFoundPlus return(term(s)); //E = T else { //E = T+T string s1(s,0,npos); //s1 = s[0] to s[npos-1] string s2(s,npos+1,len-npos+1);//s2=s[npos+1] to end of s2 return(term(s1) && term(s2)); } E = T + T | T T = F * F | F F = letter | (E) int main(){ string s = "A+B*C"; if (expression(s)) cout<<s<<" EXP.\n"; else cout<<s<<" NOT EXP.\n"; return 0; }
42
C++ bool factor(const string& s){ //F = letter | (E)
bool expression(const string& s); bool isletter(char c){ return (c>='a' && c<='z')||(c='A' && c<='Z'); } bool factor(const string& s){ //F = letter | (E) if (s.length()==1 && isletter(s[0])) return true; else { string ss(s,1,s.length()-2); return((s[0]>='(')&&(s[2]>=')')&& expression(ss)); } C++ bool term(const string& s){ //T = F*F | F size_t npos = s.find("*"); size_t len = s.length(); if (npos<0 || npos>=len){ //notFoundStar return(factor(s)); //T = F }else { //T = F*F string s1(s,0,npos); //s1 = s[0] to s[npos-1] string s2(s,npos+1,len-npos+1);//s2=s[npos+1] to end of s2 return(factor(s1) && factor(s2)); }
งานนำเสนอที่คล้ายกัน
© 2024 SlidePlayer.in.th Inc.
All rights reserved.