# 2022-9-recursive-1.pptx

1 de Jun de 2023
1 de 28

### 2022-9-recursive-1.pptx

• 1. Review the operation of recursive function/method in system stack Lai, AF
• 2. Recursion is everywhere • In general, to solve a problem using recursion, you break it into subproblems. Each subproblem • is the same as the original problem, but smaller in size. You can apply the same approach to each subproblem to solve it recursively.
• 3. A recursive function • A recursive function can be defined as a routine that calls itself directly or indirectly. • Using the recursive algorithm, certain problems can be solved quite easily. This technique provides a way to break complicated problems down into simple problems which are easier to solve. • base case : One critical requirement of recursive functions is the termination point or base case. Every recursive program must have a base case to make sure that the function will terminate (終止條件:termination condition). Missing base case results in unexpected behavior. • Implement: • The method is implemented using an if−else or a switch statement that leads to different cases. • One or more base cases (the simplest case) are used to stop recursion. • Every recursive call reduces the original problem, bringing it increasingly closer to a base case until it becomes that case. • three types of recursion : Head Recursion, Tail Recursion, Body Recursion • https://www.geeksforgeeks.org/recursive-functions/ • https://www.w3schools.com/java/java_recursion.asp
• 4. Head Recursion、 Tail Recursion • Tail recursion is the act of calling a recursive function at the end of a particular code module rather than in the middle. • A call is head-recursive when the first statement of the function is the recursive call.
• 5. Data structure when executing machine codes • System stack、run time stack、execution stack • Local variables • Activation record、Activation frame • Heap • Dymanic data, such as linked list、arraylist • Data segment • Global variable • Code segment
• 6. Recursive operation in system stack: 1 static int s(int n){ if (n<=1) return (1); else return (n+s(n-1));} Caller: r=s(5); 1. 主程式R=s(5);主程式r=s(5);呼叫s(5),無法完 成,被push到system stack頂端 2. 呼叫s(5):進入s函式本體執行 return(5+s(4)) ,but 無法完成,被push到 system stack頂端，但需呼叫s(4); 3. 呼叫s(4):):進入s函式本體執行 return(4+s(3)) ,but 無法完成,被push到 system stack頂端，但需呼叫s(3); 4. 呼叫s(3):):進入s函式本體執行 return(3+s(2)) ,but 無法完成,被push到 system stack頂端，但需呼叫s(2); 5. 呼叫s(2):):進入s函式本體執行 return(2+s(1)) ,but 無法完成,被push到 system stack頂端，但需呼叫s(1); 6. 呼叫s(1):進入本體，執行base case之 return(1), 結束遞迴，將system頂端的 return(2+s(1)) , pop出來執行，即計算s(2)之 結果2+1,且return(2+1)； 7. 將system頂端的return(3+s(2)) , pop出來執 行, 且接收return結果，即計算s(3)之結果 3+3,且return(6)； 8. 將system頂端的return(4+s(3)) , pop出來執 行, 且接收return結果，即計算s(4)之結果 4+6,且return(10)； 9. 將system頂端的return(5+s(4)) , pop出來執 行, 且接收return結果，即計算s(5)之結果 5+10,且return(15)； 10. 將system頂端的r=s(5) ,pop出來執行, s(5)之 結果15 assign給r execution stack return(2+s(1)) return(3+s(2)) return(4+s(3)) return(5+s(4)) r=s(5); top pop
• 7. Recursive operation in system stack: 2 static int s(int n){ System.out.print(n); if (n<=1) return (1); else return (n+s(n-1));} Caller: int r; r=s(5); System.out.print(n); Its result? 1. 主程式R=s(5);主程式r=s(5);呼叫s(5),無法完 成,被push到system stack頂端 2. 呼叫s(5):進入s函式本體執行 return(5+s(4)) ,but 無法完成,被push到 system stack頂端，但需呼叫s(4); 3. 呼叫s(4):):進入s函式本體執行 return(4+s(3)) ,but 無法完成,被push到 system stack頂端，但需呼叫s(3); 4. 呼叫s(3):):進入s函式本體執行 return(3+s(2)) ,but 無法完成,被push到 system stack頂端，但需呼叫s(2); 5. 呼叫s(2):):進入s函式本體執行 return(2+s(1)) ,but 無法完成,被push到 system stack頂端，但需呼叫s(1); 6. 呼叫s(1):進入本體，執行base case之 return(1), 結束遞迴，將system頂端的 return(2+s(1)) , pop出來執行，即計算s(2)之 結果2+1,且return(2+1)； 7. 將system頂端的return(3+s(2)) , pop出來執 行, 且接收return結果，即計算s(3)之結果 3+3,且return(6)； 8. 將system頂端的return(4+s(3)) , pop出來執 行, 且接收return結果，即計算s(4)之結果 4+6,且return(10)； 9. 將system頂端的return(5+s(4)) , pop出來執 行, 且接收return結果，即計算s(5)之結果 5+10,且return(15)； 10. 將system頂端的r=s(5) ,pop出來執行, s(5)之 結果15 assign給r System stack return(2+s(1)) return(3+s(2)) return(4+s(3)) return(5+s(4)) r=s(5); top pop
• 8. Illustration of the stack allocation (a) before, (b) during, and (c) after the procedure call. Figure 2.16 shows the state of the stack before, during, and after the procedure call. \$fp \$sp High address Low address a. b. c. Saved argument registers (if any) Saved return address Saved saved registers (if any) Local arrays and structures (if any) \$fp \$sp \$sp \$fp Activation record /frame
• 9. The MIPS memory allocation for program and data. Stack Dynamic data SS heap DS (global variable) CS (code segment) Static data Text Reserved \$sp 7fff fffchex 1000 8000hex 1000 0000hex \$gp 0040 0000hex pc 0 \$gp: access static data (local variable)
• 10. import java.util.Scanner; public class dec_bin2 { public static void main(String[] args) { Scanner input = new Scanner(System.in); int z, sign=1; double rn=0, fract; String bin1="", bin2=""; while (rn>=-99) { bin1=""; bin2=""; System.out.print("輸入數值含小數："); rn = input.nextDouble(); if (rn<-99) System.exit(-1); if (rn<0) { sign=-1; rn=rn*(-1); } z=(int) rn; System.out.println(rn+" 經(int)之type casting變成"+z); fract=rn-z; bin1=toint(z); bin2=tofloat(fract); String res1; res1=(sign==-1)? “-”+rn+“轉換為二進制得”+“-”+bin1+“.”+bin2 : rn+"轉換為二進制得"+bin1+"."+bin2; System.out.println(res1); //================= bin1=Rtoint(z); bin2=Rtofloat(fract); res1=(sign==-1)?"-"+rn+"轉換為二進制得"+"-"+bin1+"."+bin2:rn+"轉換為二進制得"+bin1+"."+bin2; System.out.println(res1); }//while }//main static String toint(int z){ String bin1=""; while (z>0) { bin1=z%2+bin1; z=z/2; } return bin1; } static String tofloat(double fract){ String bin2=""; int tmp; while (fract>0) { fract=fract*2; tmp=(int)fract; fract=fract-tmp; bin2=bin2+tmp; } return bin2; }
• 11. 同樣的名字與不同的參數 import java.util.Scanner; public class dec_bin2 { public static void main(String[] args) { Scanner input = new Scanner(System.in); int z; double rn=0, fract; String bin1="", bin2=""; while (rn>=0) { bin1=""; bin2=""; System.out.print("輸入數值含小數："); rn = input.nextDouble(); z=(int) rn; fract=rn-z; bin1=convert(z); System.out.println("整數："+bin1); bin2=convert(fract); System.out.println("小數："+bin2); System.out.println(rn+"轉換為二進制得"+bin1+"."+bin2); }//while }//main }//class static String convert(int x) { //整數 String bin=""; while (x>0) { bin=x%2+bin; x=x/2; } return(bin); }//convert(int x) static String convert(double x){ //小數 String bin=""; int tmp; while (x>0) { x=x*2; tmp=(int)x; x=x-tmp; bin=bin+tmp; } return(bin); }//convert(double x)
• 12. import java.util.Scanner; public class dec_bin2 { public static void main(String[] args) { Scanner input = new Scanner(System.in); int z, sign=1; double rn=0, fract; String bin1="", bin2=""; while (rn>=-99) { bin1=""; bin2=""; System.out.print("輸入數值含小數："); rn = input.nextDouble(); if (rn<-99) System.exit(-1); if (rn<0) { sign=-1; rn=rn*(-1); } z=(int) rn; System.out.println(rn+" 經(int)之type casting變成"+z); fract=rn-z; bin1=toint(z); bin2=tofloat(fract); String res1; res1=(sign==-1)?"-"+rn+"轉換為二進制得"+"-"+bin1+"."+bin2:rn+"轉換為二進制得"+bin1+"."+bin2; System.out.println(res1); //================= bin1=Rtoint(z); bin2=Rtofloat(fract); res1=(sign==-1)?"-"+rn+"轉換為二進制得"+"-"+bin1+"."+bin2:rn+"轉換為二進制得"+bin1+"."+bin2; System.out.println(res1); }//while }//main static String Rtoint(int z){ if (z>0) return (Rtoint(z/2)+""+z%2); else return ""; } static String Rtofloat(double fract){ if (fract>0) { fract=fract*2; int tmp=(int)fract; return (tmp+""+Rtofloat(fract-tmp)); } else return ""; }
• 13. 迴文 left=0;right=str1.length()-1; palindrome=pali(str1,left, right); dif=(palindrome)?"是迴文!":"不是迴文!"; System.out.println(str1+dif); left=0;right=str1.length()-1; palindrome=Rpali(str1,left, right); dif=(palindrome)?"是迴文!":"不是迴文!"; System.out.println(str1+dif); static boolean pali(String str1, int left, int right) { while (left<right) { if (str1.charAt(left)!=str1.charAt(right)) return(false); left++;right--; } //while return(true); } static boolean Rpali(String str1, int left, int right) { if (left<right) { if (str1.charAt(left)!=str1.charAt(right)) return(false); else return pali(str1,left+1,right-1); } else return(true); } public static boolean isPalindrome(String s) { if (s.length() <= 1) // Base case return true; else if (s.charAt(0) != s.charAt(s.length() − 1)) // Base case return false; else return isPalindrome( s.substring(1, s.length() − 1) ); } pali_2.java
• 14. Judge prime number System.out.print("輸入>=2整數："); n = input.nextInt(); if (n<=0) break; prime=true; i=2; while (i*i<=n) { if (n%i==0) {prime=false; break;} ++i; } dif=(prime)?"是質數!":"不是質數!"; System.out.println(n+dif); //==================== prime=isPrime(n); dif=(prime)?"是質數!":"不是質數!"; System.out.println(n+dif); //==================== prime=R_isPrime(n, 2); dif=(prime)?"是質數!":"不是質數!"; System.out.println(n+dif); static boolean isPrime(int n) { int i=2; while (i*i<=n) { if (n%i==0) { return (false); } ++i; } return (true); } static boolean R_isPrime(int n, int i) { //int i=2; if (i*i<=n) { if (n%i==0) { return (false); } return (R_isPrime(n, i+1)); } return (true); } prime_2.java
• 15. import java.util.Scanner; public class linear_search_2 { static int [] A={15, 28, 45, 51, 60, 68, 75, 81, 90, 99}; public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int score=99, idx=-1; while (score>=0) { System.out.print("請輸入欲尋找分數(>=0): "); score = scanner.nextInt(); if (score<0) break; idx=linearsearch(A, score); if (idx>=0) System.out.println("1.欲尋找分數"+score+" 在A["+idx+"]"); else System.out.println("1.欲尋找分數"+score+" 不在A陣列中"); idx=Rlinearsearch(A, score, 0); if (idx>=0) System.out.println("2.欲尋找分數"+score+" 在A["+idx+"]"); else System.out.println("2.欲尋找分數"+score+" 不在A陣列中"); } }//main() static int linearsearch(int refsc[],int num) { int i=0; int len=refsc.length; while (i<=len-1) { System.out.println("尋找次數:第"+(i+1)+"次"); if (refsc[i]==num) //Ascending return (i); else i++; }//while return (-1); //not found!! }//lsearch static int Rlinearsearch(int refsc[],int num, int i) { int len=refsc.length; if (i<=len-1) { System.out.println("尋找次數:第"+(i+1)+"次"); if (refsc[i]==num) //Ascending return (i); else return Rlinearsearch(refsc, num, ++i); } return (-1); //not found!! } }//class
• 16. binary search二分搜尋法 public class bin_search_1 { static int [] A={15, 28, 45, 51, 60, 68, 75, 81, 90, 99}; public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int score=99, idx=-1; while (score>=0) { System.out.print("請輸入欲尋找分數: "); score = scanner.nextInt(); if (score<0) break; idx=binarysearch(A, score); if (idx>=0) System.out.println("欲尋找分數"+score+" 在A["+idx+"]"); else System.out.println("欲尋找分數"+score+" 不在A陣列中"); } }//main() static int binarysearch(int refsc[],int num) { int low=0,mid=0,high=0, cnt=1; high=refsc.length-1; while (low<=high) { System.out.println("尋找次數"+cnt+"次"); mid=(int)((low+high)/2); if (refsc[mid]<num) //Ascending low=mid+1; else if (refsc[mid]>num) high=mid-1; else return (mid); cnt++; }//while return (-1); //not found!! }//binarysearch }//class
• 17. static int Rbinarysearch(int refsc[],int num,int low, int high) { int mid=0; mid=(int)((low+high)/2); if (low>high) return (-1); //not found!! else if (refsc[mid]<num) //Asce return (Rbinarysearch(refsc,num,mid+1,high)); else if (refsc[mid]>num) //Asce return (Rbinarysearch(refsc,num,low,mid-1)); else //if (refsc[mid]==num) return (mid)); }// Rbinarysearch //static關鍵字讓程式被OS載入時函式被儲存於記憶體中，直 到Application結束為止。 RBinary search //用遞迴的二元搜索 21 33 44 66 76 89 99 0 6 low high mid 3
• 18. GCD import java.util.Scanner; import java.io.*; public class GCD_all{ static int fib[]; public static void main(String args[]) { int n1=0,n2=0,result=0; fib=new int[100]; System.out.println("----求二數之最大公因數GCD----"); try { Scanner input = new Scanner(System.in); System.out.print("正整數1:(>=2)"); n1=input.nextInt(); System.out.print("正整數2:(>=2)"); n2=input.nextInt(); } catch (Exception e) { System.exit(-1);} if (n1<2 || n2<2) System.exit(-1); result=gcd(n1,n2); System.out.println("recursive:gcd("+n1+","+n2+")="+result);// using the loop approach 1-- substraction result=gcd_loop1(n1,n2); System.out.println("輾轉相減法:gcd("+n1+","+n2+")="+result);// using the loop approach 2--divide result=gcd_loop2(n1,n2); System.out.println("輾轉相除法:gcd("+n1+","+n2+")="+result); }//main static int gcd_loop1(int m, int n) { while (m!=n) { while (m>n) m=m-n; while (m<n) n=n-m; } return (m); } static int gcd_loop2(int m, int n) { int t; if (m<n) { t=m;m=n;n=t; } while (n!=0) { t=m%n; m=n; n=t; } return (m); } static int gcd(int m, int n) { int temp; if (m<n) {temp=m; m=n; n=temp; } if (m%n==0) return (n); else return ( gcd(n, m%n) ); }//gcd static int gcd_loop1b(int m, int n) { if (m!=n) { if (m>n) return gcd_loop1b(m-n, n); if (m<n) return gcd_loop1b(m, n-m); } return (m); } }//class
• 19. selection_sort public class Rselection_sort{ public static void main(String[] args){ int max=0,i=0, j=0, tmp=0; int [] data2={78,66,50,90,45,88,89,40,30,40}; System.out.println("before descending sorting"); for(i=0;i<=data2.length-1; i++) System.out.println("data2["+i+"]="+data2[i]); rsort(data2, 0); // ssort(data2); System.out.println("after descending sorting"); for(i=0;i<=data2.length-1; i++) System.out.println("data2["+i+"]="+data2[i]); }//main static void ssort(int [] data2){ int max,i, j, tmp; for(i=0;i<=data2.length-2; i++){ max=i; for (j=i+1;j<=data2.length-1;j++) if (data2[max]<data2[j]) max=j; tmp=data2[i]; data2[i]=data2[max]; data2[max]=tmp; } }//ssort static void rsort(int [] data, int i){ int max=i, j, tmp; if (i<=data.length-2) { for (j=i+1;j<=data.length-1;j++) if (data[max]<data[j]) max=j; tmp=data[i]; data[i]=data[max]; data[max]=tmp; rsort(data, i+1); } }//rsort
• 20. Fibonacci series,using • 優缺: recursive & nonrecursive approach • f(n)=1.....n=1,2 • f(n)=f(n-1)+f(n-2).....n>2 • 1,1,2,3,5,8,13,21,34,35,....
• 21. FIB import java.util.Scanner; import java.io.*; public class fib_all{ static int fib[]; public static void main(String args[]) { int n=0,result=0; fib=new int[100]; try { Scanner input = new Scanner(System.in); System.out.print("求第?位之前fib數:(>=3)"); n=input.nextInt(); } catch (Exception e) { System.exit(-1);} if (n<3) System.exit(-1); // solution 1:not use array fib_nonarray(n); //usinf array to store fib number fib_nonrecursive(n); for(int i=1;i<=n;i++) System.out.print(fib[i]+" "); System.out.println("n"); //using recursive approach for(int i=1;i<=n;i++) System.out.print(fib_recursive(i)+" "); System.out.println("n"); } //main static void fib_nonarray(int n) { int first=1,second=1,next=0; first=second=1; System.out.print(first +" "+second+" "); for(int i=3;i<=n;i++) { next=first+second; System.out.print(next+" "); second=first; first=next; }//for System.out.println(“n”); } static void fib_nonrecursive(int n) { fib[1]=fib[2]=1; for(int i=3;i<=n;i++) fib[i]=fib[i-1]+fib[i-2]; } static int fib_recursive(int n) { if (n<=2) return 1; else return (fib_recursive(n-1)+fib_recursive(n-2)); }
• 22. HextoDec import java.util.Scanner; public class HextoDec2 { public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.print("Enter a Hex number: "); String hex = input.nextLine(); System.out.println("The decimal value for hex number " + hex + " is " + hexToDecimal(hex.toUpperCase())); int decimalValue; decimalValue =R_hexToDecimal(hex.toUpperCase(),0, 0); System.out.println("The decimal value for hex number " + hex + " is " +decimalValue); }//main public static int R_hexToDecimal(String hex, int i, int decimalValue) { char hexChar; if (i < hex.length()) { hexChar = hex.charAt(i); decimalValue = decimalValue * 16 + hexCharToDecimal(hexChar); return R_hexToDecimal(hex,i+1, decimalValue); } else return (decimalValue); } public static int hexToDecimal(String hex) { int decimalValue = 0; char hexChar; for (int i = 0; i < hex.length(); i++) { hexChar = hex.charAt(i); decimalValue = decimalValue * 16 + hexCharToDecimal(hexChar); //System.out.println(hexCharToDecimal(hexChar)); //System.out.println(decimalValue); } return decimalValue; } public static int hexCharToDecimal(char ch) { if (ch >='A' && ch <='F') return 10+ch-'A'; else // ch is '0', '1', ..., or '9' return ch-‘0‘; } }//class
• 23. CC(7);//執行結果，印出:754211 CC(6);//執行結果，印出:6431 DD(8);//執行結果，印出:8754211 static void CC(int n) { System.out.print(n); if (n>1) DD(n-2); else System.out.print(n); } static void DD(int n) { System.out.print(n); if (n>1) CC(n-1); } CC(2-1) DD(4-2) CC(5-1) DD(7-2) CC(7) main() CC() DD() CC() DD() 印出7 印出5 印出4 印出2 CC() 印出1 印出1 Activation record for main()
• 24. String sta=xx(6); System.out.println(sta); String stb=yy(6); System.out.println(stb); static String xx(int n){ if (n<=1) return (""+n); else return (n+xx(n-2)); } static String yy(int n){ if (n<=1) return (""+n); else return (yy(n-2)+n); } return (“0"); return (2+xx(2-2)); return (4+xx(4-2)); return (6+xx(6-2)); sta=xx(6); After calling, OS will create activation record in execution stack Activation record for xx() xx() xx() xx() Activation record for main() Pop & return(“0”) Pop & return(2+“0”) Pop & return(4+“20”) Pop & return(6+“420”)
• 25. String stb=yy(6); System.out.println(stb); static String yy(int n){ if (n<=1) return (""+n); else return (yy(n-2)+n); } yy(6-2)+”6” yy(4-2)+”4”+”6” yy(2-2)+”2”+”4”+”6” “0”+”2”+”4”+”6” return (“0"); return (2+xx(2-2)); return (4+xx(4-2)); return (6+xx(6-2)); sta=xx(6); After calling, OS will create activation record in execution stack Activation record for xx() xx() xx() xx() Activation record for main() Pop & return(“0”) Pop & return(2+“0”) Pop & return(4+“20”) Pop & return(6+“420”)
• 27. time complexity of Fibonacci • loop solution: • The time complexity of the iterative code is linear, as the loop runs from 2 to n, i.e. it runs in O(n) time • Recursive solution: • for n > 1: T(n) = T(n-1) + T(n-2) + 4 (1 comparison, 2 subtractions, 1 addition) • the time taken by recursive Fibonacci is O(2^n) or exponential. • https://syedtousifahmed.medium.com/fibonacci-iterative-vs- recursive-5182d7783055
• 28. T(n) = T(n-1) + T(n-2) + c = 2T(n-1) + c //from the approximation T(n-1) ~ T(n-2) = 2*(2T(n-2) + c) + c = 4T(n-2) + 3c = 8T(n-3) + 7c = 2^k * T(n - k) + (2^k - 1)*c Let's find the value of k for which: n - k = 0 k = n T(n) = 2^n * T(0) + (2^n - 1)*c = 2^n * (1 + c) – c i.e. T(n) ~ O(2^n)