Download presentation
Presentation is loading. Please wait.
Published byDavid Harvey Modified over 9 years ago
1
Recursive data structures noter ch.3 Modeling recursive structure by class hierarchy Recursive traversal of structure
2
Recursive data structure Recursive structure: –list, tree Object oriented representation –Interface –Implementing classes Traversal of recursive structure –External recursive method –Internal recursive method (Composite design pattern) –Visitor design pattern
3
File system single file or a directory containing (smaller) file systems
4
Binary tree a leafor an internal node (root) and two smaller trees
5
Binary tree example: recursive expression An expression is either –a constant, or –an operator and two smaller expressions
6
Recursive structure
7
Classes for modeling recursive expression public interface Tree { } public class Leaf implements Tree { private int value; public Leaf(int n) { value = n; } public int getValue() { return value; } } public class Node implements Tree { private Operator op; private Tree left; private Tree right; public Node(Tree l, Operator o, Tree r) { op = o; left = l; right = r; } public Operator getOp() { return op; } public Tree getLeft() { return left; } public Tree getRight() { return right; } }
8
Enumeration type: Operator Recall how to make enumeration type public enum Operator { PLUS("+"), MINUS("-"), MULT("*"), DIV("/"); private String name; private Operator(String name) { this.name = name; } public String toString() { return name; } public int apply(int left, int right) { if (this == Operator.PLUS) return left + right; if (this == Operator.MINUS) return left - right; if (this == Operator.MULT) return left * right; /* this == Operator.DIV */ return left / right; }
9
representation of an expression Tree t = new Node( new Leaf(6), Operator.PLUS, new Node( new Node(new Leaf(8),Operator.MULT,new Leaf(2)), Operator.MINUS, new Leaf(1) ) );
10
QUIZ Which UML diagram models recursive bullet lists best? 1. 2. 3. 4. 5. I don’t know
11
Traversal of recursive structure traversal –calculate value of expression –print expression traversal techniques –external recursive method –internal mutually recursive methods (composite pattern) –visitor pattern
12
traversal: expression evaluation post order traversal: visit children (subexpressions) before visiting root node (operator) evaluate(v): if v is a leaf: return number stored at v else x = evaluate(left subexpression stored at v) y = evaluate(right subexpression stored at v) return x o y (where o is operator stored at v)
13
evaluation by single external recursive method public int evaluate(Tree w) { int answer; if ( w instanceof Leaf ) answer = ((Leaf)w).getValue(); else { Tree l = ((Node)w).getLeft(); Tree r = ((Node)w).getRight(); Operator o = ((Node)w).getOp(); int left_answer = evaluate(l); int right_answer = evaluate(r); answer = o.apply(left_answer,right_answer); } return answer; } instanceof-test necessary Java technicality: lots of casts obscures the code
14
a simple bullet list containing smaller lists a smaller sublist a tiny list with several entries look: recursive lists! For QUIZ: HTML source code
15
QUIZ Which – if any – errors arise? 1.Compiler error(s) 2.Runtime exceptions 3.No errors – method is correct! 4.I don’t know public String print(HTML h) { String result = ""; if (h instanceof Text) result = h.getText(); else { result += " "; for (HTML k : h.getEntries()) result += " "+print(k)+" "; result += " "; } return result; }
16
internal mutually recursive methods Ensure that all classes implementing Tree define a getValue method In interface Tree public abstract int getValue(); in class Leaf : public int getValue() { return value; } in class Node : public int getValue() { return op.apply(left.getValue(), right.getValue()); } instanceof-tests and casts are no longer necessary!
17
Node expr1 = new Node( new Leaf(8), Operator.MULT, new Node( new Leaf(5), Operator.PLUS, new Leaf(2) ) ); Example: 8 * (5 + 2)
18
expr1.getValue()
19
QUIZ Which – if any – errors arise? 1.Compiler error(s) 2.Runtime exceptions 3.No errors! 4.I don’t know Code in class BulletList: public String getText() { String result = " "; for (HTML h : getEntries()) result += " "+h.getText()+" "; return result+" "; }
20
Comparing traversal techniques external recursive method: –obscures code by instanceof test and casts internal mutually recursive methods: –for each new kind of traversal it is necessary to mess around with the code of all classes to insert new methods Visitor pattern (avoids above problems): –inserts a single method in all classes once and for all –these methods make call back to problem specific external methods
21
Visitor design pattern Decoupling of Tree hierarchy and problem specific traversal. The Tree hierarchy is prepared by adding an accept method capable of performing callback A problem specific traversal (such as value computation) requires an implementation of interface TreeVisitor
23
Modification of Tree classes The recursive structure is prepared (once and for all) by adding an accept method to Tree and all its implementing classes In interface Tree public T accept(TreeVisitor v) ; In class Leaf public T accept(TreeVisitor v){ return v.visitLeaf(this); } In class Node public T accept(TreeVisitor v){ return v.visitNode(this); } callback to problem specific method callback to problem specific methods defined by external visitor
24
Problem specific TreeVisitor A problem specific traversal requires an implementation of interface TreeVisitor : public interface TreeVisitor { public T visitLeaf(Leaf l); public T visitNode(Node n); } For traversal, the TreeVisitor methods send the tree object an accept message. The accept methods in turn make call back to the appropriate visitLeaf or visitNode method methods visitLeaf / visitNode and accept are mutually recursive.
25
Visitor example: expression evaluation instanceof test not needed (handled by call back) class EvaluateVisitor implements TreeVisitor { public Integer visitLeaf(Leaf l) { return l.getValue(); } public Integer visitNode(Node n) { int l = n.getLeft().accept(this); int r = n.getRight().accept(this); return n.getOp().apply(l,r); }
26
Example: 8 * (5 + 2) expr1.accept(new EvaluateVisitor())
27
Example: Expression evaluation Given some tree Tree t =... Evaluate by external recursive method evaluate(t) or by internal mutually recursive methods t.getValue() or by using visitor pattern t.accept(new EvaluateVisitor())
28
QUIZ How would you declare accept in interface HTML ? 1.public E accept(HTMLVisitor v); 2.public E accept(HTMLVisitor v); 3.public String accept(HTMLVisitor v); 4.public String accept(PrintVisitor v); 5.I don’t know public class PrintVisitor implements HTMLVisitor { public String visitText(Text t) { return t.getText(); } public String visitBulletList(BulletList b) { String result = " "; for (HTML h : b.getEntries()) result += " "+h.accept(this)+" "; return result+" ”; }
29
traversal: printing expression in order traversal: visit left child (subexpression) before visiting root node (operator), and finally visit right child text(v): if v is a leaf: return number else return "(" + text( left subexpression) + operator + text( right subexpression ) + ")"
30
Printing expression using visitor Computing String representation of expression (printing) class PrintVisitor implements TreeVisitor { public String visitLeaf(Leaf l) { return new Integer(l.getValue()).toString(); } public String visitNode(Node n) { return ("(" + n.getLeft().accept(this) + n.getOp() + n.getRight().accept(this) + ")"); } Application: System.out.println(t.accept(new PrintVisitor()));
31
Traversal example: drawing expression state : a current drawing position (x,y) initially (x,y) = (0,0) drawSymbol(s): increment x and draw s; draw(v): if v is a leaf: drawSymbol( number ); else increment y; draw( left subexpression ); decrement y; drawSymbol( operator ); increment y; draw( right subexpression ); decrement y; pseudocode ignores connection lines.
32
Adding connection lines to drawing state : a current drawing position (x,y) initially (x,y) = (0,0) drawSymbol(s): // returns position where s is drawn increment x and draw s; return (x,y) draw(v): // returns where root of expression is drawn if v is a leaf: return drawSymbol( number ); else increment y; l = draw( left subexpression ); decrement y; c = drawSymbol( operator ); draw line from l to c; increment y; r = draw( right subexpression ); decrement y; draw line from r to c; return c; drawing of connection lines requires that draw methods return positions for later use
33
class Draw... class DrawVisitor extends JComponent implements TreeVisitor { private static final int UNIT = 30; private Tree t; private Point pen_pos; private Graphics2D g; public DrawVisitor(Tree t) { this.t = t; JFrame f = new JFrame(); f.add(this); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setSize(400,400); f.setVisible(true); }... public void paintComponent(Graphics g) { this.g = (Graphics2D)g; pen_pos = new Point(UNIT,UNIT); t.accept(this); }
34
... implements TreeVisitor private Point drawSymbol(Object ob) { pen_pos.x += UNIT; g.drawString(ob.toString(),pen_pos.x,pen_pos.y-4); return (Point) pen_pos.clone(); } public Point visitLeaf(Leaf l) { return drawSymbol( new Integer(l.getValue()) ); } public Point visitNode(Node n) { pen_pos.y += UNIT; Point left_pos = n.getLeft().accept(this); pen_pos.y -= UNIT; Point node = drawSymbol(n.getOp()); g.draw(new Line2D.Double(left_pos,node)); pen_pos.y += UNIT; Point right_pos = n.getRight().accept(this); pen_pos.y -= UNIT; g.draw(new Line2D.Double(right_pos,node)); return node; }
35
Actual drawing made by new DrawVisitor(t) where Tree t = new Node(new Leaf(6),Operator.PLUS, new Node(new Node(new Leaf(8),Operator.MULT, new Leaf(2)),Operator.MINUS,new Leaf(1)));
36
Recursive list the empty list [ ] or an element followed by a shorter list [ 2, 7, 13, 1]
37
class hierarchy representing list Interface public interface ConsList {} class representing empty list public class Nil implements ConsList {} class representing element and shorter list public class Cons implements ConsList { private Object hd; private ConsList tl; public Cons(Object x, ConsList y) { hd = x; tl = y; } } The list ["Easter","Xmas"] may be represented as new Cons("Easter",new Cons("Xmas",new Nil())).
38
public interface ConsListVisitor { public T visitNil(Nil n); public T visitCons(Cons c); }
39
ConsList classes prepared for visits The recursive structure is prepared (once and for all) by adding an accept method In interface ConsList abstract T accept(ConsListVisitor v); In class Nil public T accept(ConsListVisitor v) { return v.visitNil(this); } In class Cons public T accept(ConsListVisitor v) { return v.visitCons(this); } callback to problem specific method callback to problem specific methods defined by external visitor
40
Problem Specific ConsListVisitor: Linear Search public class SearchVisitor implements ConsListVisitor { private Object key; public SearchVisitor(Object k) { key = k; } public Boolean visitNil(Nil n) { return false; } public Boolean visitCons(Cons c) { return c.head().equals(key) || c.tail().accept(this); } Search in recursive list l by l.accept(new SearchVisitor("Xmas"));
41
(simple) labyrinth empty labyrinthor a wall and two smaller labyrinths =
42
Recursive labyrinth: solving it while constructing it...
43
...solving it while constructing it
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.