Download presentation
Presentation is loading. Please wait.
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!
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.