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

Slides:



Advertisements
Similar presentations
C OMP 110 R ECURSION Instructor: Jason Carter. 2 R ECURSION English Return (Oxford/Webster) procedure repeating itself indefinitely or until condition.
Advertisements

Introduction to Recursion and Recursive Algorithms
Recursion English –Return (Oxford/Webster) –procedure repeating itself indefinitely or until condition met, such as grammar rule (Webster) adequate: satisfactory.
C OMP 401 D YNAMIC D ISPATCH AND A BSTRACT M ETHODS Instructor: Prasun Dewan.
Computer Science II Recursion Professor: Evan Korth New York University.
Unit 181 Recursion Definition Recursive Methods Example 1 How does Recursion work? Example 2 Problems with Recursion Infinite Recursion Exercises.
Slides prepared by Rose Williams, Binghamton University Chapter 11 Recursion.
Programming with Recursion
Slides prepared by Rose Williams, Binghamton University Chapter 11 Recursion.
Loops More loops Off-by-one errors Infinite loops Nested Loops.
Recursion Road Map Introduction to Recursion Recursion Example #1: World’s Simplest Recursion Program Visualizing Recursion –Using Stacks Recursion Example.
Stacks. 2 What is a stack? A stack is a Last In, First Out (LIFO) data structure Anything added to the stack goes on the “top” of the stack Anything removed.
1 Chapter 18 Recursion Dale/Weems/Headington. 2 Chapter 18 Topics l Meaning of Recursion l Base Case and General Case in Recursive Function Definitions.
Recursion.
Stacks (Revised and expanded from CIT 591). What is a stack? A stack is a Last In, First Out (LIFO) data structure Anything added to the stack goes on.
Stacks. 2 What is a stack? A stack is a Last In, First Out (LIFO) data structure Anything added to the stack goes on the “top” of the stack Anything removed.
Stacks. What is a stack? A stack is a Last In, First Out (LIFO) data structure Anything added to the stack goes on the “top” of the stack Anything removed.
Recursion Programming –Method calling itself. –On a smaller problem. –Alternative to loops. Word definitions: –adequate: satisfactory –satisfactory: adequate.
1 Chapter 7 Recursion. 2 What Is Recursion? l Recursive call A method call in which the method being called is the same as the one making the call l Direct.
Recursion A recursive function is a function that calls itself either directly or indirectly through another function. The problems that can be solved.
19-Aug-15 Simple Recursive Algorithms. 2 A short list of categories Algorithm types we will consider include: Simple recursive algorithms Backtracking.
Recursion James Wright St Peter’s Secondary School 733 Parkhill Road West Peterborough,Ontario K9J-8M4
20-1 Computing Fundamentals with C++ Object-Oriented Programming and Design, 2nd Edition Rick Mercer Franklin, Beedle & Associates, 1999 ISBN
Recursion. Basic problem solving technique is to divide a problem into smaller subproblems These subproblems may also be divided into smaller subproblems.
Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.
Recursion. Basic problem solving technique is to divide a problem into smaller sub problems These sub problems may also be divided into smaller sub problems.
Chapter 13 Recursion. Topics Simple Recursion Recursion with a Return Value Recursion with Two Base Cases Binary Search Revisited Animation Using Recursion.
Information and Computer Sciences University of Hawaii, Manoa
Slides prepared by Rose Williams, Binghamton University ICS201 Lecture 19 : Recursion King Fahd University of Petroleum & Minerals College of Computer.
1 Lecture 14 Chapter 18 - Recursion. 2 Chapter 18 Topics l Meaning of Recursion l Base Case and General Case in Recursive Function Definitions l Writing.
1 Chapter 13 Recursion. 2 Chapter 13 Topics l Meaning of Recursion l Base Case and General Case in Recursive Function Definitions l Writing Recursive.
1 C++ Plus Data Structures Nell Dale Chapter 7 Programming with Recursion Modified from the slides by Sylvia Sorkin, Community College of Baltimore County.
Recursion Textbook chapter Recursive Function Call a recursive call is a function call in which the called function is the same as the one making.
224 3/30/98 CSE 143 Recursion [Sections 6.1, ]
Computer Science Department Data Structure & Algorithms Lecture 8 Recursion.
Chapter 8 Recursion Modified.
Chapter 13 Recursion. Learning Objectives Recursive void Functions – Tracing recursive calls – Infinite recursion, overflows Recursive Functions that.
1 Wright State University, College of Engineering Dr. T. Doom, Computer Science & Engineering CS 241 Computer Programming II CS 241 – Computer Programming.
Data Structures & Algorithms Recursion and Trees Richard Newman.
CSC 221: Recursion. Recursion: Definition Function that solves a problem by relying on itself to compute the correct solution for a smaller version of.
IB Computer Science Unit 5 – Advanced Topics Recursion.
CS 367 Introduction to Data Structures Lecture 6.
1 Recursion Recursion is a powerful programming technique that provides elegant solutions to certain problems. Chapter 11 focuses on explaining the underlying.
TREES K. Birman’s and G. Bebis’s Slides. Tree Overview 2  Tree: recursive data structure (similar to list)  Each cell may have zero or more successors.
Chapter 7 Programming with Recursion. What Is Recursion? Recursive call A method call in which the method being called is the same as the one.
Recursion A recursive definition is one which uses the word or concept being defined in the definition itself Example: “A computer is a machine.
Recursion Chapter 17 Instructor: Scott Kristjanson CMPT 125/125 SFU Burnaby, Fall 2013.
M180: Data Structures & Algorithms in Java Stacks Arab Open University 1.
Course: Programming II - Abstract Data Types HeapsSlide Number 1 The ADT Heap So far we have seen the following sorting types : 1) Linked List sort by.
Click to edit Master text styles Stacks Data Structure.
CS 116 Object Oriented Programming II Lecture 13 Acknowledgement: Contains materials provided by George Koutsogiannakis and Matt Bauer.
Program Development and Design Using C++, Third Edition
CSC 143 P 1 CSC 143 Recursion [Chapter 5]. CSC 143 P 2 Recursion  A recursive definition is one which is defined in terms of itself  Example:  Compound.
C OMP 401 D YNAMIC D ISPATCH AND V IRTUAL AND A BSTRACT M ETHODS Instructor: Prasun Dewan.
Recursion Powerful Tool
CS314 – Section 5 Recitation 9
Introduction to Recursion
Instructor: Prasun Dewan
Recursion A problem solving technique where an algorithm is defined in terms of itself A recursive method is a method that calls itself A recursive algorithm.
Java Software Structures: John Lewis & Joseph Chase
Programming with Recursion
Map interface Empty() - return true if the map is empty; else return false Size() - return the number of elements in the map Find(key) - if there is an.
Comp 401 Dynamic Dispatch and Virtual and Abstract Methods
Applied Algorithms (Lecture 17) Recursion Fall-23
Data Structures & Algorithms
Stacks.
Stacks & Recursion.
Unit 3 Test: Friday.
Stacks.
CS210- Lecture 3 Jun 6, 2005 Announcements
Presentation transcript:

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 –  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 boy boy little boy little Smart little boy smart Recursive definition

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)

Defining factorial(n) factorial (n)= 1 factorial (n)= n* factorial(n-1) if n == 0 if 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; 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 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

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 Stack

Tracing Recursive Calls

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) / 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); }

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 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!

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)

Defining power(base, exponent) power (base, exponent)= 1if 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”

Defining greet(n) (edit) greet (1) print “hello” greet (0)greet (2)greet(n) n times print “hello”

Defining greet(n) (edited) greet (1) print “hello” greet (0)greet (2)greet(n) n times 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” greet(0); print “hello”; greet(1); print “hello”; do nothing; greet(n-1); print “hello”;

Defining greet(n) greet(n)if n <= 0 greet(n)if n > 0 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})= 1if remaining input is: -1 multiplyList ({2 -1})= 2if remaining input is: 2 -1 multiplyList ({6 2 -1})= 2*6 if remaining input is:

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)= 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) }

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

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 this static void print(StringHistory strings) { System.out.println("******************"); StringEnumeration stringEnumeration = strings.elements(); while (stringEnumeration.hasMoreElements()) { System.out.println(stringEnumeration.nextElement()); } System.out.println("******************"); } //edit this 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 (edited) //edit this static void print(StringHistory strings) { System.out.println("******************"); StringEnumeration stringEnumeration = strings.elements(); print(stringEnumeration); System.out.println("******************"); } //edit this static 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 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("******************"); }

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 cal Infinite 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 Title public 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 (edit) Course matchTitle (title, courses)

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)toppop ()

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 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("******************"); }

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);

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

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 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 ("}"); }

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 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

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

Trees C D E F B A G H subtree composite component

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

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 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

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 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); }

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); }

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; else return 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 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

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”

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”

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”

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

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 functionobjectresultarg “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 matchTitlecourses functionobjectresult matchTitlecourses.contents[1] arg “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 matchTitlecourses functionobjectresultarg “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[] new Integer(114) Found. Prog COMP 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[] new Integer(114) Found. Prog COMP Object[] COMPComp. Animation Object[] COMPComp. Animation Object[] static CourseList courseArrayToCourseList (Object[] courseArray)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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 course static CourseList courseArrayToCourseList (Object[] courseArray) { }

static CourseList courseArrayToCourseList (Object[] courseArray) (edited) // gets an array representing a set of courses rather than an individual course static 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 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; }

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 methods Additional leaf methods

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

Composite design pattern with no special leaf methods TreeNode Composite

Composite design pattern with no special composite methods TreeNode Leaf

Composite design pattern with no special leaf or composite methods TreeNode

Composite design pattern with multiple leaf/composite types TreeNode Leaf1Composite1Leaf2 Composite2

Composite design pattern with leaf/component hierarchies TreeNode LeafComposite Leaf1Composite1Leaf2Composite2

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

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

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

Hierarchical Window Tree frame Panel TextFieldButtonTextFieldButton Container Component

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

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

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 –  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 boy boy little boy little Smart little boy smart Recursive definition

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 []

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

Describing Iteration with Kleene * Iterative solution described using Kleene * –  * 5 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("******************"); }  *

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]

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

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 ("}"); }  * 

Grammar for pure tree recursion (edit) Hybrid recursive and iterative decomposition –  * – 

Grammar for pure tree recursion (edited) Hybrid recursive and iterative decomposition –  – --> – --> empty

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

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 ("}"); }

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 (edit) * 3

Grammar for simple expression (edited) * 3 ->

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

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 –  *

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

Grammar for nested expression (edited) 5 + () + (4 * (3/2))  -> ( )

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

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!