cse 21 introduction to computing ii...how to write a recursive function 9 step 1 - write and define...
TRANSCRIPT
1
CSE 21
Intro to Computing II
Functions (continued) and Recursion
1
Week of 09/24 - Lecture #4-5 (09/26), Lab #5 Week of 10/01 - Lecture #6 (10/01), Lab #6 Week of 10/08 - Midterm Review (10/10), Lab #7, Project 1 Due Week of 10/15 - Midterm (10/17), NO LAB
Schedule
2
Due on Monday October 8th at midnight
Project #1
Wednesday October 17th, in class, 50 minutes long Closed book, no notes, no computers Covers CSE020, anything from the labs, anything from lecture
Up to last lecture (lecture #6) and last lab (Lab #7) Will have a review on October 10th Extended Office Hours from TAs and Lecturer
Midterm
Same concept as name overloading ◦ Use same names, but JAVA knows which is which
Function Overloading ◦ Two or more functions that have Same modifiers (i.e., public static)
Same return type (i.e., void)
Same function name (i.e., print)
Different number of parameters and/or type
Examples ◦ public static void print()
◦ public static void print(String name)
◦ public static void print(String name, int grade)
◦ public static void print(String[] name, int[] grade)
◦ public static void print(String city, String zip)
◦ public static void print(String city, int zip)
◦ public static int print(String city)
Function Overloading
3
public static int getAmount(Scanner input, String name) { // 1
System.out.print("Enter the amount of " + name + ": ");
int amount = input.nextInt();
return amount;
}
public static void getAmount(Scanner input, String[] names, int[] amounts) { // 2
for (int i = 0; i < names.length; i++) {
System.out.print("Enter the amount of " + names[i] + " : ");
amounts[i] = input.nextInt();
}
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int sharp = getAmount(input, "Sharp");
int brie = getAmount(input, "Brie");
int swiss = getAmount(input, "Swiss");
getAmount(input, names, amounts);
Function Overloading Example
2 input parameters: Scanner + String
3 input parameters: Scanner + String pointer + int pointer
2 arguments: Scanner + String
3 arguments: Scanner + String[] + int[]
Order of the Types determine the function call 4
getAmount(input, “Random”); ◦ Scanner + String // Match 1
getAmount(“Random”, input); ◦ String + Scanner // Don’t match
getAmount(input, names[0]); ◦ Scanner + String // Match 1
getAmount(input, names); ◦ Scanner + String[] // Don’t match
getAmount(input, names, amounts); ◦ Scanner + String[] + int[] // Match 2
getAmount(input, amounts, names); ◦ Scanner + int[] + String[] // Don’t match
getAmount(input,names[0],amounts[0]); ◦ Scanner + String + int // Don’t match
getAmount(input, names, new int[MAXCHEESE]); ◦ Scanner + String[] + int[] // Match 2
getAmount(input, names, prices); ◦ Scanner + String[] + double[] // Don’t match
Matching Function Calls
public static int getAmount(Scanner input, String name) { // 1
public static void getAmount(Scanner input, String[] names, int[] amounts) { // 2
5
Can call a function anywhere in your code ◦ From the main function (as I have shown in class)
◦ From another function
Example ◦ public static void main(){
◦ greet(“Ben”);
◦ }
◦ public static void welcomeMsg() {
◦ System.out.println(“Welcome to CSE021”);
◦ }
◦ public static void greet(String name) {
◦ welcomeMsg();
◦ System.out.println(“Greetings, ” + name + “!”);
◦ }
Calling Functions Outside main
OUTPUT:
Welcome to CSE021
Greetings, Ben!
6
Can we have a function that calls itself? ◦ Yes!
What happens in that case?
Let’s try it out… ◦ public static void main(){
◦ greet(“Ben”);
◦ }
◦ public static void welcomeMsg() {
◦ System.out.println(“Welcome to CSE021”);
◦ welcomeMsg();
◦ }
◦ public static void greet(String name) {
◦ welcomeMsg();
◦ System.out.println(“Greetings, ” + name + “!”);
◦ }
This Begs the Question…
OUTPUT:
Welcome to CSE021
Welcome to CSE021
Welcome to CSE021
Welcome to CSE021
…
Infinite “Loop”!
7
We introduce a new term, Recursive Function ◦ A function that calls itself
Difficult concept to grasp ◦ Function behaves exactly the same when it is calling itself
◦ Recursion is similar to loops
◦ Function parameters are used to stop the recursion
Easy to get infinite loop
◦ Study and Practice are both necessary
Understanding/Exploiting Recursion ◦ Follow a series of steps
◦ Trace the code and function calls
Recursive Function
8
Divide the problem into smaller sub-problems ◦ Divide and conquer
◦ Same concept as using functions
The solved small problems together solve the big problem
Theoretical Example ◦ Problem: print the elements of an array
◦ Sub-problem: print one element of an array
◦ Solving the sub-problem “array.length” times will print the array
◦ The sub-problem is what goes inside the function, which calls itself
◦ Needs to make sure we have a stopping condition
Without one, we get an infinite loop
Practical Example ◦ public static void print(int[] arr, int indexToPrint) {
◦ if(indexToPrint==arr.length) return;
◦ System.out.println(arr[indexToPrint]);
◦ print(arr, indexToPrint+1);
◦ }
How to Write a Recursive Function
9
Step 1 - Write and define the recursive Function Header ◦ Your main choices are the Return Type and Parameters
Step 2 – Write out a sample/example Function Call ◦ Make sure that the call will do what you want “in theory”
◦ You might realize that your Function Header is incorrect
Step 3 – Think when you want to stop the recursion ◦ This is similar to the condition in of a loop and is called Stopping Condition
◦ You will use it to stop the function from calling itself
◦ Without a Stopping Condition we will have an infinite loop
Step 4 – Write the function body ◦ This is what the function does
Step 5 – Make the function call itself ◦ The function call will solve a smaller problem than the current one
◦ This is done by changing one or more parameters
◦ Similar to a for or a while loop
Writing Recursive Functions
10
Problem Statement: print an entire array
Sub-problem: print an element in the array
Step 1 - Write and define the recursive Function Header ◦ public static void print(int[] arr, int indexToPrint)
Step 2 – Write out a sample/example Function Call ◦ int[] arr={1,5,9,6,7}; print(arr, 0);
Step 3 – Think when you want to stop the recursion ◦ if(indexToPrint==arr.length) return;
Step 4 – Write the function body ◦ System.out.println(arr[indexToPrint]);
Step 5 – Make the function call itself ◦ print(arr, indexToPrint+1);
Final Function ◦ public static void print(int[] arr, int indexToPrint) {
◦ if(indexToPrint==arr.length) return;
◦ System.out.println(arr[indexToPrint]);
◦ print(arr, indexToPrint+1);
◦ }
Example #1 of the Process
11
To make sure our recursive function works, we must trace it
Final Function ◦ public static void print(int[] arr, int indexToPrint) {
◦ if(indexToPrint==arr.length) return;
◦ System.out.println(arr[indexToPrint]);
◦ print(arr, indexToPrint+1);
◦ }
Call from main ◦ int[] arr={1,5,9,6,7}; print(arr, 0);
Trace Output
print(arr, 0) 1
print(arr, 1) 5
print(arr, 2) 9
print(arr, 3) 6
print(arr, 4) 7
print(arr, 5)
Tracing Example #1
12
Problem Statement: print an entire array in reverse order
Sub-problem: print an element in the array
Step 1 - Write and define the recursive Function Header ◦ public static void print(int[] arr, int indexToPrint)
Step 2 – Write out a sample/example Function Call ◦ int[] arr={1,5,9,6,7}; print(arr, arr.length-1);
Step 3 – Think when you want to stop the recursion ◦ if(indexToPrint==-1) return;
Step 4 – Write the function body ◦ System.out.println(arr[indexToPrint]);
Step 5 – Make the function call itself ◦ print(arr, indexToPrint-1);
Final Function ◦ public static void print(int[] arr, int indexToPrint) {
◦ if(indexToPrint==-1) return;
◦ System.out.println(arr[indexToPrint]);
◦ print(arr, indexToPrint-1);
◦ }
Example #2 of the Process
13
To make sure our recursive function works, we must trace it
Final Function ◦ public static void print(int[] arr, int indexToPrint) {
◦ if(indexToPrint==-1) return;
◦ System.out.println(arr[indexToPrint]);
◦ print(arr, indexToPrint-1);
◦ }
Call from main ◦ int[] arr={1,5,9,6,7}; print(arr, arr.length-1);
Trace Output
print(arr, 4) 7
print(arr, 3) 6
print(arr, 2) 9
print(arr, 1) 5
print(arr, 0) 1
print(arr, -1)
Tracing Example #2
14
◦ public static void print(int[] arr, int indexToPrint) {
◦ if(indexToPrint==arr.length) return;
◦ System.out.println(arr[indexToPrint]);
◦ print(arr, indexToPrint+1);
◦ }
◦ public static void print(int[] arr, int indexToPrint) {
◦ if(indexToPrint==arr.length) return;
◦ print(arr, indexToPrint+1);
◦ System.out.println(arr[indexToPrint]);
◦ }
◦ Call from main: int[] arr={1,5,9,6,7}; print(arr, 0);
Trace Output
print(arr, 0) 7
print(arr, 1) 6
print(arr, 2) 9
print(arr, 3) 5
print(arr, 4) 1
print(arr, 5)
The Order Matters…
Prints in Order
Prints in
Reverse Order!
15
Problem Statement: sum all integers between 1 and max
Sub-problem: sum one integer with the rest of the numbers
Step 1 - Write and define the recursive Function Header ◦ public static int sumAll(int max)
Step 2 – Write out a sample/example Function Call ◦ int sum = sumAll(5); // sum should be set to 5+4+3+2+1=15
Step 3 – Think when you want to stop the recursion ◦ if(max==0) return 0; // You have to return 0, because your return type is int!
Step 4 – Write the function body ◦ The function body will be empty for this one, the sum is in the return statement
Step 5 – Make the function call itself ◦ return sumAll(max-1) + max;
Final Function ◦ public static int sumAll(int max) {
◦ if(max==0) return 0;
◦ return sumAll(max-1) + max;
◦ }
Example #3 of the Process
16
Declaration and Invocation
public static long sumAll(int max) { // Declaration System.out.println("sumAll " + n);
if (max == 0) return 0; else return sumAll(max - 1) + n; }
public static void main(String[] args) {
System.out.println("sumAll output for 5 is " + sumAll(5)); System.out.println("sumAll output for 10 is " + sumAll(10)); System.out.println("sumAll output for 20 is " + sumAll(20)); System.out.println("sumAll output for 15 is " + sumAll(15)); System.out.println();
}
17
Tracing sumAll(2) public static long sumAll(2) { System.out.println("sumAll " + 2);
if (2 == 0) return 0; else return 2 + sumAll(2 - 1); }
OUTPUT: sumAll 2
18
Tracing sumAll(2) public static long sumAll(2) { System.out.println("sumAll " + 2);
if (2 == 0) return 0; else return 2 + sumAll(2 - 1); }
OUTPUT: sumAll 2 sumAll 1
public static long sumAll(1) { System.out.println("sumAll " + 1);
if (1 == 0) return 0; else return 1 + sumAll(1 - 1); }
Invoke
19
Tracing sumAll(2) public static long sumAll(2) { System.out.println("sumAll " + 2);
if (2 == 0) return 0; else return 2 + sumAll(2 - 1); }
OUTPUT: sumAll 2 sumAll 1 sumAll 0
public static long sumAll(1) { System.out.println("sumAll " + 1);
if (1 == 0) return 0; else return 1 + sumAll(1 - 1); }
Invoke
public static long sumAll(0) { System.out.println("sumAll " + 0);
if (0 == 0) return 0;
Invoke
20
Tracing sumAll(2) public static long sumAll(int 2) { System.out.println("sumAll " + 2);
if (2 == 0) return 0; else return 2 + sumAll(2 - 1); }
OUTPUT: sumAll 2 sumAll 1 sumAll 0
public static long sumAll(int 1) { System.out.println("sumAll " + 1);
if (1 == 0) return 0; else return 1 + 0; }
Invoke
21
Tracing sumAll(2) public static long sumAll(int 2) { System.out.println("sumAll " + 2);
if (2 == 0) return 0; else return 2 + 1; }
OUTPUT: sumAll 2 sumAll 1 sumAll 0 sumAll of 2 is 3
public static void main(String[] args) {
System.out.println("sumAll of 2 is " +sumAll(2)); }
22
Any iterative solution can be converted to a recursive solution
Any recursive solution can be converted to an iterative solution
Iterative
◦ subTotal = 0;
◦ for (int i = 1; i <= max ; i++) {
◦ subTotal += i;
◦ }
Recursive
◦ public static int sumAll(int n) {
◦ if (n == 0)
◦ return 0;
◦ else
◦ return sumAll(n-1) + n;
Iterative vs Recursive
23
Missing the stopping condition ◦ public static int sumAll(int max) {
◦ return sumAll(max-1) + max;
◦ }
◦ Infinite Loop!
Wrong Function Call - no guarantee that the function will exit ◦ public static int sumAll(int max) {
◦ if(max==0) return 0;
◦ return sumAll(max-1) + max;
◦ }
◦ Calling the function with sumAll(-1) will result in an Infinite Loop!
Too many function calls ◦ Your computer has limited memory
◦ You will run out of space when calling sumAll(50000)
◦ Should not happen in this class!
Takes too much time to compute ◦ Should not happen in this class!
Common Recursion Mistakes
24
Problem Statement: compute the factorial of a number
Sub-problem: multiply one integer with the rest of the numbers
Step 1 - Write and define the recursive Function Header ◦ public static int Fact(int number)
Step 2 – Write out a sample/example Function Call ◦ int factorial = Fact(5); // factorial should be set to 5*4*3*2*1=120
Step 3 – Think when you want to stop the recursion ◦ if(number==1) return 1; // You have to return 1, your return type is int!
Step 4 – Write the function body ◦ The function body is empty; the multiplication is in the return statement
Step 5 – Make the function call itself ◦ return Fact(number-1) * number;
Final Function ◦ public static int Fact(int number) {
◦ if(number==1) return 1;
◦ return Fact(number-1) * number;
◦ }
Example #4 of the Process
25
Tracing Fact(5)
Fact(5)
Fact(4)
Fact(3)
Fact(2)
Fact(1)
Fact(1)
Return 1
Fact (2)
Return 1*2
Fact (3)
Return 2*3
Fact (4)
Return 6*4
Fact (5)
Return 24*5
public static int Fact(int number)
{
if(number==1) return 1;
return Fact(number-1) * number;
}
Call from main: Fact(5)
26
Problem Statement: compute the fibonacci of a number
Sub-problem: add the previous two numbers together
Step 1 - Write and define the recursive Function Header ◦ public static int Fib(int number)
Step 2 – Write out a sample/example Function Call ◦ int fibonacci = Fib(5); // fibonacci should be set to 2+3=5
Step 3 – Think when you want to stop the recursion ◦ if(number==0) return 0;
◦ If(number==1) return 1;
Step 4 – Write the function body
Step 5 – Make the function call itself ◦ return Fib(number-1) + Fib(number-2);
Final Function ◦ public static int Fib(int number) {
◦ if(number==1) return 1;
◦ return Fib(number-1) * number;
◦ }
Example #5 of the Process
27
Fib(5)
Fib(4)1
Fib(3)1
Fib(2)1 Fib(1)1
Fib(2)2
Fib(3)2
Fib(2)3 Fib(1)2
Tracing Fib(5)
28