Presentation is loading. Please wait.

Presentation is loading. Please wait.

Recursion Programming –Method calling itself. –On a smaller problem. –Alternative to loops. Word definitions: –adequate: satisfactory –satisfactory: adequate.

Similar presentations


Presentation on theme: "Recursion Programming –Method calling itself. –On a smaller problem. –Alternative to loops. Word definitions: –adequate: satisfactory –satisfactory: adequate."— Presentation transcript:

1 Recursion Programming –Method calling itself. –On a smaller problem. –Alternative to loops. Word definitions: –adequate: satisfactory –satisfactory: adequate –recursion: recursion Mathematics –expression giving successive terms of a series (Oxford) English –procedure repeating itself indefinitely or until condition met, such as grammar rule (Webster)

2 Grammars Noun Phrases –boy –little boy –smart little boy –naughty smart little boy Structure decompositions formally described by grammar rules –  Words within angle brackets called non-terminals There may be multiple rules describing a non-terminal Rules describe valid sequences of terminals –naughty smart little boy –think of terminals as type instances boy boy little boy little smart little boy smart Recursive definition

3 Recursive Methods Recursive Functions and Procedures Number-based Recursion List-based Recursion Tree-based Recursion

4 factoroial (n) public static int factorial (int n) { int product = 1; while (n > 0) { product *= n; n -= 1; } return product; } public static void main (String[] args) { while (true) {// loop condition never false int n = readInt(); if (n < 0) break; System.out.println(“factorial =“ + factorial(n); } 1*2*3*4 … n

5 Defining factorial(n) Product of the first n numbers. 1*2*3*4 … n factorial (0)= 1 factorial (1)= 1= 1* factorial(0) factorial (2)= 2*1= 2* factorial(1) factorial (3)= 3*2*1= 3* factorial(2) factorial (4)= 4*3*2*1= 4* factorial(3) factorial (n) = n*n-1*..*1= n* factorial(n-1)

6 Defining factorial(n) factorial (n)= 1 factorial (n)= n* factorial(n-1) if n == 0 if n > 0

7 Implementing factorial(n) factorial (n)= 1 factorial (n)= n* factorial(n-1) if n == 0 if n > 0 public static int factorial (int n) { if (n == 0) return 1; if (n > 0) return n*factorial(n-1); } Function must return something for all cases n < 0 ?

8 Implementing factorial(n) factorial (n)= 1 factorial (n)= n* factorial(n-1) if n == 0 if n > 0 public static int factorial (int n) { if (n == 0) return 1; else if (n < 0) return factorial(-n); else return n*factorial(n-1); } Recursive reduction steps Base case factorial (n)= factorial(-n)if n < 0

9 General form of Recursive Method if (base case 1 ) return solution for base case 1 else if (base case 2) return solution for base case 2 …. else if (base case n) return solution for base case n else if (recursive case 1) do some preprocessing recurse on reduced problem do some postprocessing … else if (recursive case m) do some preprocessing recurse on reduced problem do some postprocessing

10 Recursion vs. Loops (Iteration) public static int factorial (int n) { if (n == 0) return 1; else if (n < 0) return factorial(-n); else return n*factorial(n-1); } public static int factorial (int n) { int product = 1; while (n > 0) { product *= n; n -= 1; } return product; } Implementation follows from definition.

11 Tracing Recursive Calls Stack

12 Tracing Recursive Calls

13 Recursion Pitfalls public static int factorial (int n) { return n*factorial(n-1); } factorial (2) 2* factorial (1) 1* factorial (0) 0* factorial (-1) -1 * factorial(-2) Infinite recursion! (Stack overflow) No base case.... Stack element allocated for each method call to store parameters. results, return address. …

14 Recursion Pitfalls factorial (2) factorial (3) / 3 factorial (4) / 4 factorial (5) / 5 factorial(6) / 6 Infinite recursion! Recurses on bigger problem.... public static int factorial (int n) { if (n == 0) return 1; else if (n < 0) return factorial(-n); else return factorial(n+1)/(n+1); }

15 Recursive Methods Should have base case(s) Recurse on smaller problem(s) - recursive calls should converge to base case(s)

16 Recursive Functions with Multiple Parameters power (base, exponent) base*base*base*…*base power (0, exponent)= 0 exponent # of times base exponent power (1, exponent)= 1 power (2, exponent) = 2*2*2…*2 (exponent times) power (3, exponent) = 3*3*3…*3 (exponent times) No pattern!

17 Recursive Functions with Multiple Parameters power (base, exponent) base*base*base*…*base exponent # of times base exponent power (base, 0)= 1 power (base, 1)= base*1= base* power(base, 0) power (base, 2)= base*base*1= base* power(base, 1) power (base, exponent)= base*power(base, exponent-1)

18 Defining power(base, exponent) power (base, exponent)= 1if exponent <= 0 power (base, exponent)= base*power(base, exponent-1)if exponent <= 0 public static double power (int base, exponent) { if (exponent == 0) return base; else if (exponent > 0) return base*power(base, exponent-1); else return 1 / power (base, -exponent) }

19 Recursive Procedures: greet(n) greet (1) print “hello” greet (0)greet (2)greet(n) n times print “hello”

20 Defining greet(n) greet (1) print “hello” greet (0)greet (2)greet(n) n times print “hello” greet(0); print “hello”; greet(1); print “hello”; do nothing; greet(n-1); print “hello”;

21 Defining greet(n) greet(n)if n <= 0 greet(n)if n > 0 do nothing; greet(n-1); print “hello”

22 Implementing greet(n) greet(n)if n <= 0 greet(n)if n > 0 public static void greet (int n) { if (n > 0) { greet(n-1); System.out.println(“hello”); } do nothing; greet(n-1); print “hello”

23 List-based recursion List –Collection objects –Enumerations –Streams Base case –Work on some items in the list Reducing a list for recursion –Working on remainder of the list

24 multiplyList(): informal defn Multiply an input stream of numbers ending with a –1 sentinel. multiplyList({a1, a2, a3, …, aN, -1}) = a1*a2…aN multiplyList({-1}) = 1;

25 List-based recursion: multiplyList() multiplyList ({-1})= 1if remaining input is: -1 multiplyList ({2 -1})= 2if remaining input is: 2 -1 multiplyList ({6 2 -1})= 2*6 if remaining input is: 6 2 -1

26 multiplyList(): formal definition multiplyList (inputStream)= 1if nextVal < 0 multiplyList (inputStream)= readNextVal()*multiplyList(inputStream)if nextVal > 0 public static int multiplyList (BufferReader inputStream) { int nextVal = readNextVal(inputStream); if (nextVal < 0) return 1; else return nextVal*multiplyList(inputStream) }

27 Tracing multiplyList() public static int multiplyList (BufferReader inputStream) { int nextVal = readNextVal(inputStream); if (nextVal < 0) return 1; else return nextVal*multiplyList() }

28 Recursion initiator public static int multiplyInputs() { return multiplyList(new BufferReader(new InputStreamReader(System.in))); }

29 Printing an Enumeration – Iterative Solution static void print(StringHistory strings) { System.out.println("******************"); StringEnumeration stringEnumeration = strings.elements(); while (stringEnumeration.hasMoreElements()) { System.out.println(stringEnumeration.nextElement()); } System.out.println("******************"); }

30 Printing an Enumeration – Recursive Solution static void print(StringHistory strings) { System.out.println("******************"); print (strings.elements()); System.out.println("******************"); } static void print (StringEnumeration stringEnumeration) { if (!stringEnumeration.hasMoreElements()) return; System.out.println(stringEnumeration.nextElement()); print (stringEnumeration); }

31 Printing an Indexed List– Iterative Solution static void print(StringHistory strings) { System.out.println("******************"); int elementNum = 0; while (elementNum < strings.size()) { System.out.println(strings.elementAt(elementNum)); elementNum++; } System.out.println("******************"); }

32 Printing an Indexed List – Recursive Solution static void print(StringHistory strings) { System.out.println("******************"); print (strings, 0); System.out.println("******************"); } static void print (StringHistory strings, int elementNo) { if (elementNo == strings.size()) return; System.out.println(strings.elementAt(elementNo)); print (strings, elementNo + 1); }

33 Var + 1 vs. Var++ static void print (StringHistory strings, int elementNo) { if (elementNo == strings.size()) return; System.out.println(strings.elementAt(elementNo)); print (strings, elementNo++); } Redundant assignment Incremented after recursive cal Infinite recursion static void print(StringHistory strings) { System.out.println("******************"); print (strings, 0); System.out.println("******************"); }

34 Printing an Indexed List – Recursive Solution static void print (StringHistory strings, int elementNo) { if (elementNo == strings.size()) return; System.out.println(strings.elementAt(elementNo)); print (strings, ++elementNo); } Redundant assignment Incremented before recursive cal static void print(StringHistory strings) { System.out.println("******************"); print (strings, 0); System.out.println("******************"); }

35 Functional Languages Only recursion, no iteration (loops). No assignment! –All variables are final. –Single assignment languages. –No incrementing of loop variable. Elaborate support for lists.

36 List-based Recursion static void print (StringHistory strings, int elementNo) { if (elementNo == strings.size()) return; System.out.println(strings.elementAt(elementNo)); print (strings, elementNo + 1); } static void print (StringEnumeration stringEnumeration) { if (!stringEnumeration.hasMoreElements()) return; System.out.println(stringEnumeration.nextElement()); print (stringEnumeration); } public static int multiplyList (BufferReader inputStream) { int nextVal = readInt(inputStream); if (nextVal < 0) return 1; else return nextVal*multiplyList(inputStream) } List Head Tail Base: process head RecurseOn: tail

37 List-based Recursion Function gets list as parameter Divides list into head and tail. Processes head in base case. Returns if empty tail. Recurses on non-empty tail. General function structure m (List l) if l.isEmpty() return; process l.head(); m(l.tail());

38 Iterative Match Title public Course matchTitle (String theTitle) { for (int courseIndex = 0; courseIndex < size; courseIndex++) { if (contents[courseIndex].getTitle().equals(theTitle)) return contents[courseIndex]; } return null; }

39 Recursive Algorithm in terms of head and tail Course matchTitle (title, courses) if courses.isEmpty() return null; if title equals courses.head().getTitle() return courses.head() else return matchTitle(title, courses.tail())

40 Recursive Match Title public Course matchTitle (String theTitle) { return matchTitle(theTitle, 0, contents); } public Course matchTitle (String theTitle, int courseIndex, Course[] contents) { if (courseIndex == size) return null; if (contents[courseIndex].getTitle().equals(theTitle)) return contents[courseIndex]; return matchTitle(theTitle, courseIndex + 1, contents); } Does not change

41 Recursive Match Title public Course matchTitle (String theTitle) { return matchTitle(theTitle, 0); } public Course matchTitle (String theTitle, int courseIndex) { if (courseIndex == size) return null; if (contents[courseIndex].getTitle().equals(theTitle)) return contents[courseIndex]; return matchTitle(theTitle, courseIndex + 1); } Global instance variable

42 Lists in functional and other languages One type representing lists –Head –Tail –isEmpty All lists instances of this class. Inefficient –Tail is copy of original items Multiple representations of list –Stream-based –Enumerations –Vector-based –Array-based –StringHistory-based –… Awkward (but more efficient) representations –Vector + index

43 Recursion vs. Iteration Recursive solutions may be a little cleaner than iterative solutions –Maybe not cleaner in list-based case because of awkward representation Solution same as definition –formal definition problem –easier to get right Are there problems where recursive solution is much simpler?

44 Printing an enumeration in reverse order static void print (StringEnumeration stringEnumeration) { if (!stringEnumeration.hasMoreElements()) return; System.out.println(stringEnumeration.nextElement()); print (stringEnumeration); } In order static void print (StringEnumeration stringEnumeration) { if (!stringEnumeration.hasMoreElements()) return; String head = stringEnumeration.nextElement(); print (stringEnumeration); System.out.println( head); } Reverse order

45 Printing an Enumeration in reverse order – loop solution static void print(StringHistory strings) { System.out.println("******************"); StringEnumeration stringEnumeration = strings.elements(); while (stringEnumeration.hasMoreElements()) { System.out.println(stringEnumeration.nextElement()); } System.out.println("******************"); } In order Loop would have to store all items in some collection object (stack) that allows items to be accessed in reverse order.

46 Stack Push –Pushes an item above existing items Pop –Removes the top item –Last in first out (LIFO) Top –Returns the top item isEmpty –Returns true if no elements. Procedure call stack –Last procedure in call chain returns first A push (A) B push (B)top

47 Stack Push –Pushes an item above existing items Pop –Removes the top item –Last in first out (LIFO) Top –Returns the top item isEmpty –Returns true if no elements. Procedure call stack –Last procedure in call chain returns first A push (A)push (B)toppop ()

48 Printing an Enumeration in reverse order – loop solution static void print(StringHistory strings) { StringStack stringStack = new AStringStack(); System.out.println("******************"); StringEnumeration stringEnumeration = strings.elements(); while (stringEnumeration.hasMoreElements()) { stringStack.push(stringEnumeration.nextElement()); } while (!stringStack.isEmpty()) { System.out.println(stringStack.top()); stringStack.pop(); } System.out.println("******************"); }

49 Printing an enumeration in reverse order Recursive solution is easier as it uses the call stack created automatically. Loop uses a manually created stack.

50 Printing an Object Array static Object[] introProg = {new Integer(14), "Intro. Prog.", "COMP"}; System.out.println(introProg); [Ljava.lang.Object;@3f5d07

51 Iteratively printing an Object Array static void print (Object[] objArray) { System.out.print("{"); for (int index = 0; index < objArray.length; index++) { System.out.print(objArray[index]); if (index < objArray.length -1) System.out.print(", "); } System.out.print ("}"); } print (introProg);{14, Intro. Prog., COMP} static Object[] introProg = {new Integer(14), "Intro. Prog.", "COMP"}; static Object[] foundProg = {new Integer(114), "Found. Prog.", "COMP"}; static Object[] programming = {introProg, foundProg}; print (programming);{[Ljava.lang.Object;@3f5d07, [Ljava.lang.Object;@f4a24a}

52 Problem One level loop  single-level arrays Loop nested in loop  array nested in array N-level loop  N-level array What if N is not known at programming writing time? Loop nesting level fixed at program writing time.

53 Desired Solution print (introProg);{14, Intro. Prog., COMP} static Object[] introProg = {new Integer(14), "Intro. Prog.", "COMP"}; static Object[] foundProg = {new Integer(114), "Found. Prog.", "COMP"}; static Object[] programming = {introProg, foundProg}; print (programming);{{14, Intro. Prog., COMP}, {114, Found. Prog., COMP}} static Object[] algorithms = {new Integer(122), "Algorithms", "COMP"}; static Object[] compAnimation = {"Comp. Animation", "COMP"}; static Object[] otherCompSci = {algorithms, compAnimation}; static Object[] compSci = {programming, otherCompSci}; print (compSci){{{14, Intro. Prog., COMP}, {114, Found. Prog., COMP}}, {{122, Algorithms, COMP}, {Comp. Animation, COMP}}}

54 Iteratively printing an Object Array static void print (Object[] objArray) { System.out.print("{"); for (int index = 0; index < objArray.length; index++) { System.out.print(objArray[index]); if (index < objArray.length -1) System.out.print(", "); } System.out.print ("}"); }

55 Recursively printing an Object Array static void print (Object[] objArray) { System.out.print("{"); for (int index = 0; index < objArray.length; index++) { Object element = objArray[index]; if (element.getClass().isArray()) print ((Object[]) element); else System.out.print(objArray[index]); if (index < objArray.length -1) System.out.print(", "); } System.out.print ("}"); } iteration recursion

56 List-based Looping and Recursion Function gets list as parameter Divides list into head and tail. Processes head in base case. Returns if empty tail. Recurses on non-empty tail. General function structure m (List l) if l.isEmpty() return; process l.head(); m(l.tail()); May consume more than one item in loop until some condition encountered which leads to recursive step

57 Trees –Items (called nodes) connected by directed arrows –Arrows describe parent child relationships –Source item called parent of destination item –Destination called children –A node can be both a parent and a child –Single root item item with no parent –Many leaf items Items with no chidren –Composite/internal node Non-leaf node –Component Node with a parent - All nodes except root –Subtree Node and all of its descendents –Height of subtree Number of nodes to leaf node along longest path C D E F B A parent children root G H Leaf item subtree Composite Component Height: 1 Height: 3 Height: 0

58 Trees C D E F B A parent children root G H height: 1 height: 3 height: 0 leaf item level: 0 level: 1 level: 2 Level Number of nodes to root node along unique path to it.

59 Object Arrays and Trees static Object[] introProg = {new Integer(14), "Intro. Prog.", "COMP"}; static Object[] foundProg = {new Integer(114), "Found. Prog.", "COMP"}; static Object[] programming = {introProg, foundProg}; static Object[] algorithms = {new Integer(122), "Algorithms", "COMP"}; static Object[] compAnimation = {"Comp. Animation", "COMP"}; static Object[] otherCompSci = {algorithms, compAnimation}; static Object[] compSci = {programming, otherCompSci}; new Integer(14) Intro Prog COMP introProg programming new Integer(114) Found. Prog COMP foundProg new Integer(122) Algori thms COMP compSci algorithms COMPComp. Animation compAnimation otherCompSci

60 Tree-based Recursion Method gets some tree item as argument Processes node. –Leaf and non-leaf processing can be different Recursion occurs on children Recursion ends when leaf node reached

61 Tree-based Recursion Function gets some tree item as argument Processes node. –Leaf and non-leaf processing can be different Recursion occurs on children Recursion ends when leaf node reached static void print (Object[] objArray) { System.out.print("{"); for (int index = 0; index < objArray.length; index++) { Object element = objArray[index]; if (element.getClass().isArray()) print ((Object[]) element); else System.out.print(objArray[index]); if (index < objArray.length -1) System.out.print(", "); } System.out.print ("}"); }

62 Tree-based Recursion static void print (Object[] objArray) { System.out.print("{"); for (int index = 0; index < objArray.length; index++) { Object element = objArray[index]; if (element.getClass().isArray()) print ((Object[]) element); else System.out.print(objArray[index]); if (index < objArray.length -1) System.out.print(", "); } System.out.print ("}"); } new Integer(14) Intro Prog COMP introProg programming new Integer(114) Found. Prog COMP foundProg new Integer(122) Algori thms COMP compSci algorithms COMPComp. Animation compAnimation otherCompSci print (compSci) print (programming) print (introProg) { { {14, Intro Prog, COMP} print (foundProg) {114, Found. Prog., COMP} } print (otherCompSci) {} print (algorithms) {122, Algorithms, COMP} print (compAnimation) {Comp. Animation., COMP} },,, Loop to process nodes at same level Recursion to go down a level

63 Pure Recursive Solution List-based recursion to process nodes at same level. Tree-based recursion to process nodes at the next level. Two different methods.

64 Pure Recursive Solution static void print (Object[] objArray, int elementNo) { if (elementNo >= objArray.length) return; else { Object element = objArray[elementNo]; if (element.getClass().isArray()) print ((Object[]) element); else System.out.print(objArray[elementNo]); if (elementNo < objArray.length -1) System.out.print(", "); print (objArray, elementNo + 1); } static void print (Object[] objArray) { System.out.print("{"); print (objArray, 0); System.out.print ("}"); } Direct recursion Indirect recursion List-based Tree-based

65 Course problem solved so far Given course information stored in flat course list Given a course, find the dept and number. new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) courses

66 Course problem solved so far new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) courses static void fillCourses() { courses.addElement(new ARegularCourse ("Intro. Prog.", "COMP", 14)); courses.addElement(new ARegularCourse ("Found. of Prog.", "COMP", 114)); courses.addElement(new AFreshmanSeminar("Comp. Animation", "COMP")); courses.addElement(new AFreshmanSeminar("Lego Robots", "COMP")); }

67 Course Tree Course information stored in hierarchical course lists. Leaf nodes are courses Given a course name, return leaf node matching title. prog new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) courses

68 Course List Tree prog new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) courses static void fillCourses() { CourseList prog = new ACourseList(); prog.addElement(new ARegularCourse ("Intro. Prog.", "COMP", 14)); prog.addElement(new ARegularCourse ("Found. of Prog.", "COMP", 114)); courses.addElement(prog); courses.addElement(new AFreshmanSeminar("Comp. Animation", "COMP")); courses.addElement(new AFreshmanSeminar("Lego Robots", "COMP")); }

69 Why trees instead of flat lists Information may come in hierarchical form from organizations –programming group submits courses to CS dept. –CS dept submits courses to arts and sciences –arts and sciences submits courses to UNC Can answer hierarchical queries –print all CS courses –print all programming courses –will not show benefit in example

70 Using Flat vs. Hierarchical Course Lists static void fillCourses() { courses.addElement(new ARegularCourse ("Intro. Prog.", "COMP", 14)); courses.addElement(new ARegularCourse ("Found. of Prog.", "COMP", 114)); courses.addElement(new AFreshmanSeminar("Comp. Animation", "COMP")); courses.addElement(new AFreshmanSeminar("Lego Robots", "COMP")); } static void fillCourses() { CourseList prog = new ACourseList(); prog.addElement(new ARegularCourse ("Intro. Prog.", "COMP", 14)); prog.addElement(new ARegularCourse ("Found. of Prog.", "COMP", 114)); courses.addElement(prog); courses.addElement(new AFreshmanSeminar("Comp. Animation", "COMP")); courses.addElement(new AFreshmanSeminar("Lego Robots", "COMP")); } CourseList Course

71 Original Course and Course List package courses; public interface Course { public String getTitle(); public String getDepartment(); public int getNumber(); public void init (String theTitle, String the Dept); } package collections; import courses.Course; public interface CourseList { public void addElement(Course element); public int size(); public Course elementAt(int index); public Course matchTitle (String theTitle); }

72 package courseTree; public interface CourseList { public void addElement(??? element); public int size(); public Course elementAt(int index); public Course matchTitle (String theTitle); } Tree Course and Course List package courseTree; public interface Course { public String getTitle(); public String getDepartment(); public int getNumber(); public void init (String theTitle, String the Dept); }

73 package courses; public interface Course { public String getTitle(); public String getDepartment(); public int getNumber(); public void init (String theTitle, String the Dept); } package collections; public interface CourseList { public void addElement(Object element); public int size(); public Course elementAt(int index); public Course matchTitle (String theTitle); } Tree Course and Course List Can put a BMISpreadsheet in it!

74 package courses; public interface Course { public String getTitle(); public String getDepartment(); public int getNumber(); public void init (String theTitle, String the Dept); } package collections; public interface CourseList { public void addElement(TreeNode element); public int size(); public Course elementAt(int index); public Course matchTitle (String theTitle); } Tree Course and Course List

75 package courses; public interface Course extends TreeNode { public String getTitle(); public String getDepartment(); public int getNumber(); public void init (String theTitle, String the Dept); } package collections; public interface CourseList extends TreeNode { public void addElement(TreeNode element); public int size(); public Course elementAt(int index); public Course matchTitle (String theTitle); } Tree Course and Course List

76 package courses; public interface Course extends TreeNode { public String getTitle(); public String getDepartment(); public int getNumber(); public void init (String theTitle, String the Dept); } package collections; public interface CourseList extends TreeNode { public void addElement(TreeNode element); public int size(); public Course elementAt(int index); public Course matchTitle (String theTitle); } Tree Course and Course List Can add Course Can add CourseList

77 Tree Node package courseTree; public interface TreeNode { } Empty for now. Will fill it based on course list operations.

78 Tree Course and Course List package courseTree; public interface CourseList extends TreeNode { public void addElement(TreeNode element); public int size(); public TreeNode elementAt(int index); public Course matchTitle (String theTitle); } Only operation requiring re- implementation

79 matchTitle in flat list Course[] contents = new Course[MAX_SIZE]; public Course matchTitle (String theTitle) { for (int courseIndex = 0; courseIndex < size; courseIndex++) { if (contents[courseIndex].getTitle().equals(theTitle)) return contents[courseIndex]; } return null; }

80 matchTitle in hierarchical list? TreeNode[] contents = new Course[MAX_SIZE]; public Course matchTitle (String theTitle) { for (int courseIndex = 0; courseIndex < size; courseIndex++) { TreeNode element = contents[courseIndex]; if (element instanceof Course) { if (((Course)element).getTitle().equals(theTitle)) return (Course) element; } else { // instance of CourseList Course course = ((CourseList) element).matchTitle(theTitle); if (course != null) return course; } return null; }

81 Using dynamic dispatch TreeNode[] contents = new TreeNode[MAX_SIZE]; public Course matchTitle (String theTitle) { for (int courseIndex = 0; courseIndex < size; courseIndex++) { Course course = contents[courseIndex].matchTitle(theTitle); if ( course != null) return course; } return null; }

82 matchTitle in ACourse package courseTree; public abstract class ACourse implements Course { public Course matchTitle(String theTitle) { if ( title.equals(theTitle)) return this; else return null; } … }

83 Final Tree Node package courseTree; public interface TreeNode { public Course matchTitle (String theTitle); }

84 Tracing matchTitle prog new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) courses matchTitlecourses functionobjectresult matchTitlecourses.contents[0] matchTitlecourses.contents[0].contents[0] arg “Comp. Animation” Same implementation on two different objects Arg does not get smaller object does Different dynamically dispatched implementations

85 Tracing matchTitle prog new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) courses matchTitlecourses functionobjectresult matchTitlecourses.contents[0] matchTitlecourses.contents[0].contents[0] arg “Comp. Animation” null “Comp. Animation”

86 Tracing matchTitle prog new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) courses matchTitlecourses functionobjectresult matchTitlecourses.contents[0] matchTitlecourses.contents[0].contents[1] arg “Comp. Animation” null “Comp. Animation”

87 Tracing matchTitle prog new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) courses matchTitlecourses functionobjectresult matchTitlecourses.contents[0] arg “Comp. Animation” null

88 Tracing matchTitle prog new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) courses matchTitlecourses functionobjectresult matchTitlecourses.contents[1] arg “Comp. Animation” courses.contents[1]

89 Recursively visiting a tree prog new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) courses

90 Recursively visiting a tree prog new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) courses

91 Recursively visiting a tree prog new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) courses

92 Recursively visiting a tree prog new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) courses

93 Recursively visiting a tree prog new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) courses

94 Recursively visiting a tree prog new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) courses

95 Recursively visiting a tree prog new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) courses

96 Recursively visiting a tree prog new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) courses

97 Recursively visiting a tree prog new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) courses

98 Recursively Visiting vs. Creating Tree Visited (traversed) tree recursively –matchTitle() So far, created fixed-size tree –Non-recursively Creating variable-size tree? –Must be done recursively as no of levels unknown

99 Problem CourseList new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) CourseList new Integer(14) Intro Prog COMP Object[] new Integer(114) Found. Prog COMP Object[] COMPComp. Animation Object[] COMPComp. Animation Object[] From a course array tree, create a course list hierarchy

100 CourseList new Integer(14) Intro Prog COMP Object[] new Integer(114) Found. Prog COMP Object[] COMPComp. Animation Object[] COMPComp. Animation Object[] static CourseList courseArrayToCourseList (Object[] courseArray)

101 CourseList new Integer(14) Intro Prog COMP Object[] new Integer(114) Found. Prog COMP Object[] COMPComp. Animation Object[] COMPComp. Animation Object[] static CourseList courseArrayToCourseList (Object[] courseArray)

102 CourseList new ARegularCourse (“Intro. Prog”, “COMP”, 14) CourseList new Integer(14) Intro Prog COMP Object[] new Integer(114) Found. Prog COMP Object[] COMPComp. Animation Object[] COMPComp. Animation Object[] static CourseList courseArrayToCourseList (Object[] courseArray)

103 CourseList new ARegularCourse (“Intro. Prog”, “COMP”, 14) CourseList new Integer(14) Intro Prog COMP Object[] new Integer(114) Found. Prog COMP Object[] COMPComp. Animation Object[] COMPComp. Animation Object[] static CourseList courseArrayToCourseList (Object[] courseArray)

104 CourseList new ARegularCourse (“Intro. Prog”, “COMP”, 14) new ARegularCourse (“Found. Prog.”, “COMP”, 114) CourseList new Integer(14) Intro Prog COMP Object[] new Integer(114) Found. Prog COMP Object[] COMPComp. Animation Object[] COMPComp. Animation Object[] static CourseList courseArrayToCourseList (Object[] courseArray)

105 CourseList new ARegularCourse (“Intro. Prog”, “COMP”, 14) new ARegularCourse (“Found. Prog.”, “COMP”, 114) CourseList new Integer(14) Intro Prog COMP Object[] new Integer(114) Found. Prog COMP Object[] COMPComp. Animation Object[] COMPComp. Animation Object[] static CourseList courseArrayToCourseList (Object[] courseArray)

106 CourseList new ARegularCourse (“Intro. Prog”, “COMP”, 14) new ARegularCourse (“Found. Prog.”, “COMP”, 114) CourseList new Integer(14) Intro Prog COMP Object[] new Integer(114) Found. Prog COMP Object[] COMPComp. Animation Object[] COMPComp. Animation Object[] static CourseList courseArrayToCourseList (Object[] courseArray)

107 CourseList new ARegularCourse (“Intro. Prog”, “COMP”, 14) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) CourseList new Integer(14) Intro Prog COMP Object[] new Integer(114) Found. Prog COMP Object[] COMPComp. Animation Object[] COMPComp. Animation Object[] static CourseList courseArrayToCourseList (Object[] courseArray)

108 CourseList new ARegularCourse (“Intro. Prog”, “COMP”, 14) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) CourseList new Integer(14) Intro Prog COMP Object[] new Integer(114) Found. Prog COMP Object[] COMPComp. Animation Object[] COMPComp. Animation Object[] static CourseList courseArrayToCourseList (Object[] courseArray)

109 CourseList new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) CourseList new Integer(14) Intro Prog COMP Object[] new Integer(114) Found. Prog COMP Object[] COMPComp. Animation Object[] COMPComp. Animation Object[] static CourseList courseArrayToCourseList (Object[] courseArray)

110 CourseList new ARegularCourse (“Intro. Prog”, “COMP”, 14) new AFreshmanSeminar (“Lego Robots”, “COMP” ) new ARegularCourse (“Found. Prog.”, “COMP”, 114) new AFreshmanSeminar (“Comp. Animation”, “COMP” ) CourseList new Integer(14) Intro Prog COMP Object[] new Integer(114) Found. Prog COMP Object[] COMPComp. Animation Object[] COMPComp. Animation Object[] static CourseList courseArrayToCourseList (Object[] courseArray)

111 Helper methods static boolean isFreshmanSeminar (Object[] courseArray) { if (courseArray.length != 2) return false; if (courseArray[0] instanceof String && courseArray[1] instanceof String) return true; else return false; } static boolean isRegularCourse (Object[] courseArray) { if (courseArray.length != 3) return false; if (courseArray[0] instanceof Integer && courseArray[1] instanceof String && courseArray[2] instanceof String) return true; else return false; }

112 Helper methods static Course courseArrayToRegularCourse (Object[] courseArray) { return (new ARegularCourse ((String) courseArray[1], (String) courseArray[2], ((Integer) courseArray[0]).intValue())); } static FreshmanSeminar courseArrayToFreshmanSeminar (Object[] courseArray) { return (new AFreshmanSeminar((String) courseArray[0], (String) courseArray[1])); }

113 static CourseList courseArrayToCourseList (Object[] courseArray) (edit) // gets an array representing a set of courses rather than an individual course static CourseList courseArrayToCourseList (Object[] courseArray) { }

114 static CourseList courseArrayToCourseList (Object[] courseArray) // gets an array representing a set of courses rather than an individual course static CourseList courseArrayToCourseList (Object[] courseArray) { CourseList courseList = new ACourseList(); for (int index = 0; index < courseArray.length; index++) { Object[] element = (Object[]) courseArray[index]; if (isFreshmanSeminar(element)) courseList.addElement(courseArrayToFreshmanSeminar(element)); else if (isRegularCourse(element)) courseList.addElement(courseArrayToRegularCourse(element)); else courseList.addElement(courseArrayToCourseList(element)); } return courseList; }

115 Using dynamic dispatch TreeNode[] contents = new TreeNode[MAX_SIZE]; public Course matchTitle (String theTitle) { for (int courseIndex = 0; courseIndex < size; courseIndex++) { Course course = contents[courseIndex].matchTitle(theTitle); if ( course != null) return course; } return null; }

116 Composite design pattern package courseTree; public interface TreeNode { public Course matchTitle (String theTitle); } package courseTree; public interface Course extends TreeNode { public String getTitle(); public String getDepartment(); public int getNumber(); } package courseTree; public interface CourseList extends TreeNode { public void addElement(TreeNode element); public int size(); public Course elementAt(int index); } Common tree node interface Additional leaf methods Additional composite methods

117 Composite design pattern TreeNode LeafComposite Common tree node interface Additional composite methods Additional leaf methods

118 Composite design pattern with no special leaf methods TreeNode Composite

119 Composite design pattern with no special composite methods TreeNode Leaf

120 Composite design pattern with no special leaf or composite methods TreeNode

121 Composite design pattern with multiple leaf/composite types TreeNode Leaf1Composite1Leaf2Composite2

122 Composite design pattern with leaf/component hierarchies TreeNode LeafComposite Leaf1Composite1Leaf2Composite2

123 Composite design pattern with interfaces TreeNode LeafComposite Common tree node interface Additional composite methods Additional leaf methods extends

124 Composite design pattern with interfaces and classes TreeNode ALeafAComposite Common tree node interface Additional composite methods Additional leaf methods implements LeafOnly CompositeOnly

125 Composite design pattern with classes only ATreeNode ALeafAComposite Common abstract class extends Additional composite methods Additional leaf methods

126 Hierarchical Window Tree frame Panel TextFieldButtonTextFieldButton Container Component

127 AWT Classes Component Container TextField PanelFrame Button TreeNode Methods General Composite Methods Specialized Composite Methods Specialized Leaf Methods

128 Creating Window Structure frame Panel TextFieldButtonTextFieldButton Frame frame = new Frame("Points Plotter"); Panel control = new Panel(); frame.add( new Panel()); control.add( new Button(“New Point”)); control.add(new Button(“Quit”); control.add(new TextField(“0”)); frame.add(control); control.add(new TextField(“0”)); Like creating hierarchical course lists in fillCourses

129 Add() definition? public void add (T element) T? –Component Class in which method defined? –Container Can we add containers to containers? –Container IS-A component

130 Leaf-specific methods TextField –getText(), setText() Cannot invoke them on buttons or containers.

131 TreeNode methods Defined in component –paint() Each concrete class implements it in its own way A container class just calls paint() on its components. Does not have to worry about how to implement it. Don’t have to change a container class as new components are implemented. No instanceof operation!

132 Grammars Noun Phrases –boy –little boy –smart little boy –naughty smart little boy Structure decompositions formally described by grammar rules –  Words within angle brackets called non-terminals There may be multiple rules describing a non-terminal Rules describe valid sequences of terminals –naughty smart little boy –think of terminals as type instances boy boy little boy little smart little boy smart Recursive definition

133 Grammar for simple expression (edit) 5 + 4 * 3

134 Grammar for simple expression 5 + 4 * 3

135 Grammar for simple expression 5 + 4 * 3  +5 4 * 5

136 Grammar for nested expression (edit) 5 + (4 * (3/2))  ????

137 Grammar for nested expression 5 + (4 * (3/2))   ( ) Terminal (matches itself only)

138 Describing lists using grammars Lists –[] –[6] –[6 5] Grammar for list –  –  empty 6 [ 6 5] 5 [ 5] empty []

139 Describing list-based tail recursion with grammars Recursive function decomposes a list into items using the following grammar: –  –  empty 6 [ 6 5] 5 [ 6] empty []

140 Printing an Enumeration – Recursive Solution static void print (StringEnumeration stringEnumeration) { if (!stringEnumeration.hasMoreElements()) return; else { System.out.println(stringEnumeration.nextElement()); print (stringEnumeration); }  empty 

141 Describing Iteration with Kleene * Iterative solution described using Kleene * –  * 5 6 [ 6 5]

142 Printing an Enumeration – Iterative Solution static void print(StringHistory strings) { System.out.println("******************"); StringEnumeration stringEnumeration = strings.elements(); while (stringEnumeration.hasMoreElements()) { System.out.println(stringEnumeration.nextElement()); } System.out.println("******************"); }  *

143 Object vs. Call Structure In both cases object is same –Flat list Structure of method calls is different –Grammar describes tree of method calls Why grammar? –Sometimes given E.g. programming language or expressions –As a high-level step before method coded 5 6 [ 6 5] empty 5 6 [ 6 5]

144 Describing tree recursion with grammars Hybrid recursive and iterative decomposition –  * –  [] 6 [[3 4 ] 6 []] 3 4

145 Recursively printing an Object Array static void print (Object[] objArray) { System.out.print("{"); for (int index = 0; index < objArray.length; index++) { Object element = objArray[index]; if (element.getClass().isArray()) print ((Object[]) element); else System.out.print(objArray[index]); if (index < objArray.length -1) System.out.print(", "); } System.out.print ("}"); }  * 

146 Grammar for pure tree recursion Pure recursive decomposition –  –  empty –  [[3 4 ] 6 []] 4 3 [] 6 Indirect recursion empty Direct recursion empty

147 Pure recursive decomposition –  –  empty –  Pure Recursive Solution static void print (Object[] objArray, int elementNo) { if (elementNo >= objArray.length) return; else { Object element = objArray[elementNo]; if (element.getClass().isArray()) print ((Object[]) element); else System.out.print(objArray[elementNo]); if (elementNo < objArray.length -1) System.out.print(", "); print (objArray, elementNo + 1); } static void print (Object[] objArray) { System.out.print("{"); print (objArray, 0); System.out.print ("}"); }

148 Structure of object vs. structure of method In both previous cases object is same –Flat list Structure of method calls is different –Grammar describes tree of method calls Why grammar? –Sometimes given E.g. programming language or expressions –As a high-level step before method coded

149 More on grammars From a theoretical point of view –Theory of computation (COMP 181) From a practical point of view –Compilers (COMP 140) Both are optional –Please take them!


Download ppt "Recursion Programming –Method calling itself. –On a smaller problem. –Alternative to loops. Word definitions: –adequate: satisfactory –satisfactory: adequate."

Similar presentations


Ads by Google