Loops More loops Off-by-one errors Infinite loops Nested Loops.
Recursion Programming –Method calling itself. –On a smaller problem. –Alternative to loops....
-
date post
19-Dec-2015 -
Category
Documents
-
view
223 -
download
0
Transcript of Recursion Programming –Method calling itself. –On a smaller problem. –Alternative to loops....
Recursion• Programming
– Method calling itself.
– On a smaller problem.
– Alternative to loops.
• English definitions:– adequate: satisfactory
– satisfactory: adequate
– recursion: recursion
• Mathematics– expression giving successive terms of a series (Oxford)
• Grammar
– procedure repeating itself indefinitely or until condition met, such as grammar rule (Webster)
Grammars• Noun Phrases
– boy
– little boy– smart little boy– naughty smart little boy
• Structure decompositions formally described by grammar rules– <Noun Phrase> <Noun>– <Noun Phrase>
<Adjective> <Noun Phrase>• Words within angle brackets called
non-terminals– think of them as types
• 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
<Noun Phrase>
boy
<Adjective> <Noun Phrase>
boy
<Noun>
little boy
little
Smart little boy
<Adjective>
smart
Recursive definition
<Noun Phrase>
Recursive Methods
• Recursive Functions and Procedures
• Number-based Recursion
• List-based Recursion
• Tree-based Recursion
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
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)
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 ?
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
General form of Recursive Methodif (base case 1 ) return solution for base case 1else if (base case 2) return solution for base case 2….else if (base case n) return solution for base case nelse 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
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.
Tracing Recursive Calls
Invocation n return valuefactorial(1) 1 ?factorial(2) 2 ?
Invocation n return valuefactorial(0) 0 ?factorial(1) 1 ?factorial(2) 2 ?
Invocation n return valuefactorial(0) 0 1factorial(1) 1 ?factorial(2) 2 ?
Invocation n return valuefactorial(0) 0 1factorial(1) 1 1factorial(2) 2 ?
Invocation n return valuefactorial(0) 0 1factorial(1) 1 1factorial(2) 2 2
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....
Recursion Pitfalls
factorial (2)
factorial (3) / 3
factorial (4) / 4
factorial (5) / 5
factorial(6) / 6Infinite 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); }
Recursive Methods
• Should have base case(s)
• Recurse on smaller problem(s) - recursive calls should converge to base case(s)
Recursive Functions with Multiple Parameters
power (base, exponent)
base*base*base*…*base
power (0, exponent) = 0
exponent # of times
baseexponent
power (1, exponent) = 1power (2, exponent) = 2*2*2…*2 (exponent times)power (3, exponent) = 3*3*3…*3 (exponent times)
No pattern!
Recursive Functions with Multiple Parameters
power (base, exponent)
base*base*base*…*base
exponent # of times
baseexponent
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)
Defining power(base, exponent)
power (base, exponent) = 1 if exponent <= 0
power (base, exponent) = base*power(base, exponent-1) if exponent <= 0
public static int power (int base, exponent) { if (n <= 0)
return base; else
return base*power(base, exponent-1); }
Recursive Procedures: greet(n)
greet (1)
print “hello”
greet (0) greet (2) greet(n)
n times
print “hello”
print “hello”
print “hello”
print “hello”
print “hello”
print “hello”
Defining greet(n) (edit)
greet (1)
print “hello”
greet (0) greet (2) greet(n)
n times
print “hello”
print “hello”
print “hello”
print “hello”
print “hello”
print “hello”
Defining greet(n) (edited)
greet (1)
print “hello”
greet (0) greet (2) greet(n)
n times
print “hello”
print “hello”
print “hello”
print “hello”
print “hello”
print “hello”
Do nothing
Greet(0)
Print hello Greet(1)
Print hello
Defining greet(n)
greet (1)
print “hello”
greet (0) greet (2) greet(n)
n times
print “hello”
print “hello”
print “hello”
print “hello”
print “hello”
print “hello”greet(0);
print “hello”; greet(1);
print “hello”;
do nothing;
greet(n-1);
print “hello”;
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”
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
List-based recursion: multiplyList()
multiplyList ({-1}) = 1 if remaining input is: -1
multiplyList ({2 -1}) = 2 if remaining input is: 2 -1
multiplyList ({6 2 -1})= 2*6 if remaining input is: 6 2 -1
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;
multiplyList(): formal defn (edit)
• Multiply an input stream of numbers ending with a –1 sentinel.
• multiplyList({a1, a2, a3, …, aN, -1}) = a1*a2…aN
• multiplyList({-1}) = 1;
• multiplyList(inputStream)
multiplyList(): formal defn (edited)
• Multiply an input stream of numbers ending with a –1 sentinel.
• multiplyList({a1, a2, a3, …, aN, -1}) = a1*a2…aN
• multiplyList({-1}) = 1;
• multiplyList(inputStream) {– int nextVal = readNextVal(inputStream);
– if (nextVal == -1) return 1;
– return nextVal*multiplyList(inputStream);
multiplyList(): formal definition
multiplyList (inputStream) = 1 if 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) }
Tracing multiplyList()
public static int multiplyList (BufferReader inputStream) { int nextVal = readNextVal(inputStream); if (nextVal < 0) return 1; else return nextVal*multiplyList() }
Invocation Remaininginput
return value
multiplyList() 2 30 -1 ???
Invocation Remaininginput
return value
multiplyList() 30 -1 ???multiplyList() 2 30 -1 ???
Invocation Remaininginput
return value
multiplyList() -1 ???multiplyList() 30 -1 ???multiplyList() 2 30 -1 ???
Invocation Remaininginput
return value
multiplyList() -1 1multiplyList() 30 -1 ???multiplyList() 2 30 -1 ???
Invocation Remaininginput
return value
multiplyList() -1 1multiplyList() 30 -1 30multiplyList() 2 30 -1 ???
Invocation Remaininginput
return value
multiplyList() -1 1multiplyList() 30 -1 30multiplyList() 2 30 -1 60
Recursion initiator
public static int multiplyInputs() { return multiplyList(new BufferReader(new InputStreamReader(System.in)));}
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("******************");
}
Printing an Enumeration – Recursive Solution (edit)
//edit thisstatic void print(StringHistory strings) {
System.out.println("******************");StringEnumeration stringEnumeration = strings.elements();while (stringEnumeration.hasMoreElements()) {
System.out.println(stringEnumeration.nextElement());}System.out.println("******************");
}
//edit thisstatic void print(StringHistory strings) {
System.out.println("******************");StringEnumeration stringEnumeration = strings.elements();while (stringEnumeration.hasMoreElements()) {
System.out.println(stringEnumeration.nextElement());}System.out.println("******************");
}
Printing an Enumeration – Recursive Solution (edited)
//edit thisstatic void print(StringHistory strings) {
System.out.println("******************");StringEnumeration stringEnumeration = strings.elements();print(stringEnumeration);System.out.println("******************");
}
//edit thisstatic void print(StringEnumeration stringEnumeration) { if (stringEnumeration.hasMoreElements()) {
System.out.println(stringEnumeration.nextElement());print(stringEnumeration);
}}
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);
}
Printing an Indexed List– Iterative Solutionstatic void print(StringHistory strings) {
System.out.println("******************");int elementNum = 0;while (elementNum < strings.size()) {
System.out.println(strings.elementAt(elementNum));elementNum++;
}System.out.println("******************");
}
Printing an Indexed List – Recursive Solution (edit)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("******************");
}
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("******************");
}
Printing an Indexed List – Recursive Solution (edited)
static void print(StringHistory strings) {System.out.println("******************");print(strings, 0);System.out.println("******************");
}
static void print(StringHistory strings, int elementNum) {if (elementNo == strings.size()) return;System.out.println(strings.elementAt(elementNum));print(strings, elementNum++);
}
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);
}
Var + 1 vs. Var++static void printEnumeration(StringHistory strings) {
//System.out.println("vector recursive");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++);
}
Redundant assignment
Incremented after recursive calInfinite recursion
Printing an Indexed List – Recursive Solution
static void printEnumeration(StringHistory strings) {//System.out.println("vector recursive");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);
}
Redundant assignment
Incremented before recursive cal
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.
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
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()); Can be done in opposite order
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
Iterative Match Titlepublic Course matchTitle (String theTitle) {
for (int courseIndex = 0; courseIndex < size; courseIndex++) {if (contents[courseIndex].getTitle().equals(theTitle))
return contents[courseIndex];}return null;
}
Recursive Algorithm in terms of head and tail (edited)
Course matchTitle (title, courses)
if courses.isEmpty() return null;
if (title.equals(courses.head().getTitle())
return courses.head()
else
return matchTitle(title, courses.tail());
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())
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
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
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?
Printing an enumeration in reverse order
static void print (StringEnumeration stringEnumeration) {if (!stringEnumeration.hasMoreElements()) return; System.out.println(stringEnumeration.nextElement());print (stringEnumeration);
}
static void print (StringEnumeration stringEnumeration) {if (!stringEnumeration.hasMoreElements()) return; print (stringEnumeration);System.out.println(stringEnumeration.nextElement());
}
In order
Reverse order
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.
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
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)
top pop ()
Printing an Enumeration in reverse order – loop solution (edit)
static void print(StringHistory strings) {System.out.println("******************");StringEnumeration stringEnumeration = strings.elements();while (stringEnumeration.hasMoreElements()) {
System.out.println(stringEnumeration.nextElement());}System.out.println("******************");
}
Printing an Enumeration in reverse order – loop solution (edited)static void print(StringHistory strings) {
Stack s = new AStack();System.out.println("******************");StringEnumeration stringEnumeration = strings.elements();while (stringEnumeration.hasMoreElements()) {
s.push(stringEnumeration.nextElement();}while (!s.isEmpty()) {
System.out.println(s.top());s.pop();
}System.out.println("******************");
}
Printing an Enumeration in reverse order – loop solutionstatic 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("******************");
}
Printing an enumeration in reverse order
• Recursive solution is easier as it uses the call stack created automatically.
• Loop uses a manually created stack.
Printing an Object Array
static Object[] introProg = {new Integer(14), "Intro. Prog.", "COMP"};
System.out.println(introProg);
[Ljava.lang.Object;@3f5d07
Iteratively printing an Object Arraystatic 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}
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.
Unknown N
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}}}
Iteratively printing an Object Arraystatic 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 ("}");
}
Recursively printing an Object Array (edit)
static void print (Object[] objArray) {
System.out.print("{");
for (int index = 0; index < objArray.length; index++) {
Object element = objArray[index];
System.out.print(objArray[index]);
if (index < objArray.length -1) System.out.print(", ");
}
System.out.print ("}");
}
Recursively printing an Object Array (edited)
static void print (Object[] objArray) {
System.out.print("{");
for (int index = 0; index < objArray.length; index++) {
Object element = objArray[index];
if (isArray(element))
print((Object[])element);
else
System.out.print(objArray[index]);
if (index < objArray.length -1) System.out.print(", ");
}
System.out.print ("}");
}
Recursively printing an Object Arraystatic 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 ("}");
}
iterationrecursion
Trees– Items (called nodes) connected by directed arrows
– Arrows describe parent child relationships– Source item called parent of destination
item– 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
– Subtree • Node and all of its descendents
– Component• Node with a parent -• All nodes except root
– Height of subtree• Number of nodes to leaf node along
longest path
– Level• Number of nodes to root node along unique
path to it.
C
D E
F
B
A
parent
children
root
G
H
Leaf item
subtree
Composite
Component
Height: 1
Height: 3
Height: 0
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
Object Arrays and Treesstatic 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)
Algorithms
COMP
compSci
algorithms
COMPComp. Animation
compAnimation
otherCompSci
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
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 ("}");}
Tree-based Recursionstatic 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)
Algorithms
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
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.
Pure recursive soln (edit)static void print (Object[] objArray) {
print (objArray, 0);}
static void print (Object[] objArray, int elementNo) {System.out.print("{");for (int index = 0; index < objArray.length; index++) {
Object element = objArray[index];System.out.print(objArray[index]);
if (index < objArray.length -1)System.out.print(", ");
}System.out.print ("}");
}
Pure recursive soln (edited)static void print (Object[] objArray) {
print (objArray, 0);}
static void print (Object[] objArray, int elementNo) {System.out.print("{");for (int index = 0; index < objArray.length; index++) {
Object element = objArray[index];System.out.print(objArray[index]);
if (index < objArray.length -1)System.out.print(", ");
}System.out.print ("}");
}
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
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
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"));}
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
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"));}
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
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
Original Course and Course Listpackage 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);
}
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 Listpackage courseTree;public interface Course {
public String getTitle();public String getDepartment();public int getNumber();public void init (String theTitle, String the Dept);
}
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!
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
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
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
Tree Node
package courseTree;public interface TreeNode {}
Empty for now.
Will fill it based on course list operations.
Tree Course and Course List
package courseTree;public interface CourseList extends TreeNode {
public void addElement(TreeNode element);public int size();public Course elementAt(int index);public Course matchTitle (String theTitle);
}
Only operation requiring re-implementation
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;
}
matchTitle in hierarchical list? (edit)
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;
}
matchTitle in hierarchical list? (edited)
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
return ((CourseList) element).matchTitle(theTitle);}
return null;}
matchTitle in hierarchical list? (edited)
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;}
matchTitle in hierarchical list? (edited)
TreeNode[] contents = new Course[MAX_SIZE];
public Course matchTitle (String theTitle) { for (int courseIndex = 0; courseIndex < size; courseIndex++) {
TreeNode element = contents[courseIndex];Course course = element.matchTitle(theTitle);if (course != null) return course;
} return null;}
matchTitle in hierarchical list
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;}
matchTitle in ACourse
package courseTree;public abstract class ACourse implements Course { public Course matchTitle(String theTitle) {
if ( title.equals(theTitle))return this;
elsereturn null;
} …}
Final Tree Node
package courseTree;public interface TreeNode {
public Course matchTitle (String theTitle);}
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
matchTitle courses
function object result
matchTitle courses.contents[0]
matchTitle courses.contents[0].contents[0]
arg
“Comp. Animation”
“Comp. Animation”
“Comp. Animation”
Same implementation on two different objects
Arg does not get smaller
object doesDifferent dynamically dispatched implementations
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
matchTitle courses
function object result
matchTitle courses.contents[0]
matchTitle courses.contents[0].contents[0]
arg
“Comp. Animation”
null
“Comp. Animation”
“Comp. Animation”
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
matchTitle courses
function object result
matchTitle courses.contents[0]
arg
“Comp. Animation”
“Comp. Animation”
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
matchTitle courses
function object result
matchTitle courses.contents[0]
matchTitle courses.contents[0].contents[1]
arg
“Comp. Animation”
null
“Comp. Animation”
“Comp. Animation”
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
matchTitle courses
function object result
matchTitle courses.contents[0]
arg
“Comp. Animation”
“Comp. Animation” null
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
matchTitle courses
function object resultarg
“Comp. Animation”
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
matchTitle courses
function object result
matchTitle courses.contents[1]
arg
“Comp. Animation”
“Comp. Animation” courses.contents[1]
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
matchTitle courses
function object resultarg
“Comp. Animation” courses.contents[1]
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
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
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
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
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
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
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
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
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
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
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[]
Object[]
new Integer(114)
Found. Prog
COMP
Object[]
Object[]
COMPComp. Animation
Object[]
COMPComp. Animation
Object[]
• From a course array tree, create a course list hierarchy
CourseList
new Integer(14)
Intro Prog
COMP
Object[]
Object[]
new Integer(114)
Found. Prog
COMP
Object[]
Object[]
COMPComp. Animation
Object[]
COMPComp. Animation
Object[]
static CourseList courseArrayToCourseList (Object[] courseArray)
CourseList
CourseList
new Integer(14)
Intro Prog
COMP
Object[]
Object[]
new Integer(114)
Found. Prog
COMP
Object[]
Object[]
COMPComp. Animation
Object[]
COMPComp. Animation
Object[]
static CourseList courseArrayToCourseList (Object[] courseArray)
CourseList
new ARegularCourse (“Intro. Prog”, “COMP” , 14)
CourseList
new Integer(14)
Intro Prog
COMP
Object[]
Object[]
new Integer(114)
Found. Prog
COMP
Object[]
Object[]
COMPComp. Animation
Object[]
COMPComp. Animation
Object[]
static CourseList courseArrayToCourseList (Object[] courseArray)
CourseList
new ARegularCourse (“Intro. Prog”, “COMP” , 14)
CourseList
new Integer(14)
Intro Prog
COMP
Object[]
Object[]
new Integer(114)
Found. Prog
COMP
Object[]
Object[]
COMPComp. Animation
Object[]
COMPComp. Animation
Object[]
static CourseList courseArrayToCourseList (Object[] courseArray)
CourseList
new ARegularCourse (“Intro. Prog”, “COMP” , 14)
new ARegularCourse (“Found. Prog.”, “COMP” , 114)
CourseList
new Integer(14)
Intro Prog
COMP
Object[]
Object[]
new Integer(114)
Found. Prog
COMP
Object[]
Object[]
COMPComp. Animation
Object[]
COMPComp. Animation
Object[]
static CourseList courseArrayToCourseList (Object[] courseArray)
CourseList
new ARegularCourse (“Intro. Prog”, “COMP” , 14)
new ARegularCourse (“Found. Prog.”, “COMP” , 114)
CourseList
new Integer(14)
Intro Prog
COMP
Object[]
Object[]
new Integer(114)
Found. Prog
COMP
Object[]
Object[]
COMPComp. Animation
Object[]
COMPComp. Animation
Object[]
static CourseList courseArrayToCourseList (Object[] courseArray)
CourseList
new ARegularCourse (“Intro. Prog”, “COMP” , 14)
new ARegularCourse (“Found. Prog.”, “COMP” , 114)
CourseList
new Integer(14)
Intro Prog
COMP
Object[]
Object[]
new Integer(114)
Found. Prog
COMP
Object[]
Object[]
COMPComp. Animation
Object[]
COMPComp. Animation
Object[]
static CourseList courseArrayToCourseList (Object[] courseArray)
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[]
Object[]
new Integer(114)
Found. Prog
COMP
Object[]
Object[]
COMPComp. Animation
Object[]
COMPComp. Animation
Object[]
static CourseList courseArrayToCourseList (Object[] courseArray)
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[]
Object[]
new Integer(114)
Found. Prog
COMP
Object[]
Object[]
COMPComp. Animation
Object[]
COMPComp. Animation
Object[]
static CourseList courseArrayToCourseList (Object[] courseArray)
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[]
Object[]
new Integer(114)
Found. Prog
COMP
Object[]
Object[]
COMPComp. Animation
Object[]
COMPComp. Animation
Object[]
static CourseList courseArrayToCourseList (Object[] courseArray)
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[]
Object[]
new Integer(114)
Found. Prog
COMP
Object[]
Object[]
COMPComp. Animation
Object[]
COMPComp. Animation
Object[]
static CourseList courseArrayToCourseList (Object[] courseArray)
Helper methods
static boolean isFreshmanSeminar (Object[] courseArray) {if (courseArray.length != 2) return false;if (courseArray[0] instanceof String) return true;else return false;
}
static boolean isRegularCourse (Object[] courseArray) {if (courseArray.length != 3) return false;if (courseArray[0] instanceof Integer) return true;else return false;
}
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]));}
static CourseList courseArrayToCourseList (Object[] courseArray) (edit)
// gets an array representing a set of courses rather than an individual coursestatic CourseList courseArrayToCourseList (Object[] courseArray) { }
static CourseList courseArrayToCourseList (Object[] courseArray) (edited)
// gets an array representing a set of courses rather than an individual coursestatic CourseList courseArrayToCourseList (Object[] courseArray) { if (isFreshmanSeminar(courseArray)) return courseArrayToFreshmanSeminar(courseArray); else (ifRegularCourse(courseArray)) return courseArrayToRegularCourse(courseArray); else { CourseList courseList = new ACourseList(); for (int index =0; index < courseArray.length; index++) courseList.addElement( courseArrayToCourseList(courseArray[index]));
return courseList; } }
static CourseList courseArrayToCourseList (Object[] courseArray)
// gets an array representing a set of courses rather than an individual coursestatic 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)); elsecourseList.addElement(courseArrayToCourseList(element)); } return courseList;}
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 composite methodsAdditional leaf methods
Composite design pattern
TreeNode
Leaf Composite
Common tree node interface
Additional composite methods
Additional leaf methods
Composite design pattern with multiple leaf/composite types
TreeNode
Leaf1 Composite1Leaf2 Composite2
Composite design pattern with leaf/component hierarchies
TreeNode
Leaf Composite
Leaf1 Composite1Leaf2 Composite2
Composite design pattern with interfaces
TreeNode
Leaf Composite
Common tree node interface
Additional composite methods
Additional leaf methods
extendsextends
Composite design pattern with interfaces and classes
TreeNode
ALeaf AComposite
Common tree node interface
Additional composite methods
Additional leaf methods
implements implements
LeafOnly CompositeOnly
Composite design pattern with classes only
ATreeNode
ALeaf AComposite
Common abstract class
extends extends
Additional composite methods
Additional leaf methods
AWT Classes
Component
Container TextField
PanelFrame
Button
TreeNode MethodsGeneral
CompositeMethods
Specialized Composite Methods
Specialized Leaf Methods
Creating Window Structure
frame
Panel Panel
TextField ButtonTextField Button
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
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
Leaf-specific methods
• TextField– getText(), setText()
• Cannot invoke them on buttons or containers.
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!
Grammars• Noun Phrases
– boy
– little boy– smart little boy– naughty smart little boy
• Structure decompositions formally described by grammar rules– <Noun Phrase> <Noun>– <Noun Phrase>
<Adjective> <Noun Phrase>• Words within angle brackets
called non-terminals– think of them as types
• There may be multiple rules describing a non-terminal
• Rules describe valid sequences of terminals– naughty smart little boy– Think of them as type instances
<Noun Phrase>
boy
<Adjective> <Noun Phrase>
boy
<Noun>
little boy
little
Smart little boy
<Adjective>
smart
Recursive definition
<Noun Phrase>
Describing list-based tail recursion with grammars
• Recursive function decomposes a list into items using the following grammar:– <List> <Item> <List>– <List> empty
<List>
<Item>
6
[ 6 5]
<List>
<Item>
5
[ 6]
<List>
empty
[]
Printing an Enumeration – Recursive Solution
static void print (StringEnumeration stringEnumeration) {if (!stringEnumeration.hasMoreElements()) return;else {
System.out.println(stringEnumeration.nextElement());print (stringEnumeration);
}}
<List> empty
<List> <Item> <List>
Describing Iteration with Kleene *
• Iterative solution described using Kleene *– <List> <Item> *
<Item>
5
<List>
<Item>
6
[ 6 5]
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("******************");
}
<List> <Item> *
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
<List>
<Item>
5
<List>
<Item>
6
[ 6 5]
empty
5
<List>
<Item>
6
[ 6 5]
Describing tree recursion with grammars
• Hybrid recursive and iterative decomposition– <TreeNode> <TreeNode >*– <TreeNode> <Item>
[]
<TreeNode>
<Item>
6
[[3 4 ] 6 []]
<TreeNode>
<TreeNode>
3
<Item>
4
<TreeNode>
<Item>
<TreeNode> <TreeNode>
Recursively printing an Object Arraystatic 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 ("}");
}
<TreeNode> <TreeNode >*
<TreeNode> <Item>
Grammar for pure tree recursion (edit)
• Hybrid recursive and iterative decomposition– <TreeNode> <TreeNode >*– <TreeNode> <Item>
Grammar for pure tree recursion (edited)
• Hybrid recursive and iterative decomposition– <TreeNode> <TreeNodeList >– <TreeNode> <Item>– <TreeNodeList> --> <TreeNode> <TreeNodeList>– <TreeNodeList> --> empty
Grammar for pure tree recursion• Pure recursive decomposition
– <TreeNode> <TreeNodeList>– <TreeNode> <Item>– <TreeNodeList> empty– <TreeNodeList> <TreeNode> <TreeNodeList>
<TreeNodeList>
[[3 4 ] 6 []]
<TreeNodeList>
4
<Item>
3<Item>
<TreeNode> <TreeNodeList>
<TreeNode> <TreeNodeList>
<TreeNode>
[]
<Item>
6
<TreeNode> <TreeNodeList>
<TreeNodeList>
Indirect recursion
<TreeNode> <TreeNodeList>
empty
Direct recursion
<TreeNode> <TreeNodeList>
empty
• Pure recursive decomposition– <TreeNode> <TreeNode List>– <TreeNode> <Item>– <Tree Node List> empty– <Tree Node List> <Tree Node> <Tree Node
List>
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 ("}");
}
}
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
Grammar for simple expression (edited)
5 + 4 * 3
<Expression> -> <Number>
<Expression> <Number> <Operator> <Expression>
Grammar for simple expression
5 + 4 * 3
<Expression> <Number>
<Expression> <Number> <Operator> <Expression>
<Expression>
+5
<Operator><Number> <Expression>
<Number>
4 *
<Operator> <Expression>
5
<Number>
Iterative vs. Recursive Solution
• Previous grammar can be used for recursive evaluation of flat lists– Extra credit to do it
• Grammar used for loop-based solution– <Expression> <Token> *
Grammar for nested expression (edit)
5 + (4 * (3/2))
<Expression> <Number>
<Expression> <Number> <Operator> <Expression>
Grammar for nested expression (edited)
5 + () + (4 * (3/2))
<Expression> <Number>
<Expression> <Number> <Operator> <Expression>
<Expression> -> (<Expression>)
Grammar for nested expression5 + (4 * (3/2))<Expression> <Number><Expression> <Number> <Operator> <Expression><Expression> ( <Expression>)
Terminal (matches itself only)