noter ch.3 Modeling recursive structure by class hierarchy ... · Recursive data structures noter ch.3 Modeling recursive structure by class hierarchy Recursive traversal of structure.

Post on 19-May-2021

18 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

Transcript

Recursive data structuresnoter ch.3

Modeling recursive structure by class hierarchy

Recursive traversal of structure

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

• Building a recursive structure– Parsing using mutually recursive methods

File system

File system

• A directory containing (smaller) file systems

• Or a single file

Arithmetic expression

• An expression is either– a constant, or– an operator and two smaller expressions

Expression as binary tree

• Recursive structureNode

Leaf

A binary tree is• an internal node (root)

and two smaller trees, or• a leaf

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

}

Enumeration type: Operatorpublic enum Operator {PLUS("+"), MINUS("-"), MULT("*"), DIV("/");private String name;private Operator(String name) { this.name = name; }public String toString() { return name; }public static Operator parseOp(String s) {

if (Operator.PLUS.name.equals(s)) return Operator.PLUS;if (Operator.MINUS.name.equals(s)) return Operator.MINUS;if (Operator.MULT.name.equals(s)) return Operator.MULT;if (Operator.DIV.name.equals(s)) return Operator.DIV;throw new UnsupportedOperationException(s);

}public int apply(int left, int right) {

switch (this) {case PLUS: return left + right; case MINUS: return left - right; case MULT: return left * right; case DIV: return left / right; default:

throw new UnsupportedOperationException(this.toString());}

}}

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)

));

Recursive bullet list

• In webbrowser • html source code<ul>

<li>a simple bullet list</li><li>containing smaller lists</li><li><ul>

<li>a smaller sublist</li><li>

<ul><li>a tiny list</li><li>with several entries</li>

</ul></li><li>look: recursive lists!</li>

</ul></li>

</ul>

QUIZ UML and recursion

Which UML diagram models recursive bullet lists best?

1.

4.

2.

3.

5. I don’t know

Traversal of recursive structure

• traversal– calculate value of expression– print expression

• traversal techniques– external recursive method– internal mutually recursive methods

(composite pattern)– visitor pattern

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

elsex = evaluate(left subexpression stored at v)y = evaluate(right subexpression stored at v)return x o y (where o is operator stored at v)

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

Recursive bullet list• In webbrowser • html source code

<ul><li>a simple bullet list</li><li>containing smaller lists</li><li><ul>

<li>a smaller sublist</li><li>

<ul><li>a tiny list</li><li>with several entries</li>

</ul></li><li>look: recursive lists!</li>

</ul></li>

</ul>

• UML model

public String print(HTML h) {String result = "";if (h instanceof Text) result = h.getText();else {

result += "<ul>";for (HTML k : h.getEntries())

result += "<li>"+print(k)+"</li>";result += "</ul>";

}return result;

}

How should the compiler errors be fixed?1. There should be no errors – update java compiler to newer version!2. Declare getText() and getEntries() in interface HTML3. Type cast h to Text and BulletList, respectively4. Fix in some other way5. I don’t know

QUIZTraversal by externalrecursive method

internal mutually recursive methods• Ensure that all classes implementing Tree define a getValue method

• In interface Treepublic 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!

Node expr1 =new Node(new Leaf(8),Operator.MULT,new Node(new Leaf(5),Operator.PLUS,new Leaf(2)

));

Example: 8 * (5 + 2)

• in class Leaf:public int getValue() { return value; }

• in class Node:public int getValue() {

int l = left.getValue();int r = right.getValue();return op.apply(l,r);

}

Example: 8 * (5 + 2)expr1.getValue()

Example: 8 * (5 + 2)expr1.getValue()

Example: 8 * (5 + 2)expr1.getValue()

Example: 8 * (5 + 2)expr1.getValue()

Example: 8 * (5 + 2)expr1.getValue()

Example: 8 * (5 + 2)expr1.getValue()

Example: 8 * (5 + 2)expr1.getValue()

Example: 8 * (5 + 2)expr1.getValue()

Recursive bullet list• In webbrowser • html source code

<ul><li>a simple bullet list</li><li>containing smaller lists</li><li><ul>

<li>a smaller sublist</li><li>

<ul><li>a tiny list</li><li>with several entries</li>

</ul></li><li>look: recursive lists!</li>

</ul></li>

</ul>

• UML model

QUIZ

Code in class BulletList:

public String getText() {String result = "<ul>";for (HTML h : getEntries())

result += "<li>"+h.getText()+"</li>";return result+"</ul>";

}

Traversal by internal recursive method

How should the compiler error be fixed?1. There should be no errors – update java

compiler to newer version!2. Declare getText() in interface HTML3. Type cast h to Text4. Type cast h to BulletList5. Fix in some other way6. I don’t know

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

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

• EvaluateVisitor is the client.• Mutually recursive accept / visitNode• Recursion stops when calling visitLeaf

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 Treepublic <T> T accept(TreeVisitor<T> v) ;

• In class Leafpublic <T> T accept(TreeVisitor<T> v){return v.visitLeaf(this);

}

• In class Nodepublic <T> T accept(TreeVisitor<T> v){return v.visitNode(this);

}

callback to problem specific method

callback to problem specific methods defined

by external visitor

Problem specific TreeVisitor• A problem specific traversal requires an implementation

of interface TreeVisitor:public interface TreeVisitor<T> {

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.

Visitor example: expression evaluation

• instanceof test not needed (handled by call back)

class EvaluateVisitor implements TreeVisitor<Integer> {

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

}}

• In class EvaluateVisitorpublic 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);

}• In class Leafpublic <T> T accept(TreeVisitor<T> v){return v.visitLeaf(this);

}

• In class Nodepublic <T> T accept(TreeVisitor<T> v){return v.visitNode(this);

}

Example: 8 * (5 + 2)expr1.accept(new EvaluateVisitor())

Example: 8 * (5 + 2)expr1.accept(new EvaluateVisitor())

Example: 8 * (5 + 2)expr1.accept(new EvaluateVisitor())

Example: 8 * (5 + 2)expr1.accept(new EvaluateVisitor())

Example: 8 * (5 + 2)expr1.accept(new EvaluateVisitor())

Example: 8 * (5 + 2)expr1.accept(new EvaluateVisitor())

Example: 8 * (5 + 2)expr1.accept(new EvaluateVisitor())

Example: 8 * (5 + 2)expr1.accept(new EvaluateVisitor())

Example: Expression evaluation

• Given some treeTree t = ...

• Evaluate by external recursive methodevaluate(t)

• or by internal mutually recursive methodst.getValue()

• or by using visitor patternt.accept(new EvaluateVisitor())

Recursive bullet list• In webbrowser • html source code

<ul><li>a simple bullet list</li><li>containing smaller lists</li><li><ul>

<li>a smaller sublist</li><li>

<ul><li>a tiny list</li><li>with several entries</li>

</ul></li><li>look: recursive lists!</li>

</ul></li>

</ul>

• UML model

QUIZ

public class PrintVisitor implements HTMLVisitor<String> {

public String visitText(Text t) { return t.getText(); }

public String visitBulletList(BulletList b) {String result = "<ul>";for (HTML h : b.getEntries()) result += "<li>"+ +"</li>";return result+"</ul>”;

}}

What code should replace ?1. b.getText()2. b.accept(this)3. b.accept(new PrintVisitor());4. h.getText()5. h.accept(this)6. h.accept(new PrintVisitor());7. None of the above8. I don’t know

Traversal by visitor

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

elsereturn "("+ text( left subexpression)+ operator+ text( right subexpression )+ ")"

Printing expression using visitor• Computing String representation of expression (printing)

class PrintVisitor implements TreeVisitor<String> {

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

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

elseincrement y;draw( left subexpression );decrement y;drawSymbol( operator );increment y;draw( right subexpression );decrement y;

pseudocode ignores connection lines.

Adding connection lines to drawingstate : a current drawing position (x,y)

initially (x,y) = (0,0)drawSymbol(s): // returns position where s is drawnincrement x and draw s;return (x,y)

draw(v): // returns where root of expression is drawnif v is a leaf:return drawSymbol( number );

elseincrement 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

class Draw ...class DrawVisitor extends JComponent implements

TreeVisitor<Point> {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);

}}

... implements TreeVisitorprivate 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;

}

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

Recursive bullet list• In webbrowser • html source code

<ul><li>a simple bullet list</li><li>containing smaller lists</li><li><ul>

<li>a smaller sublist</li><li>

<ul><li>a tiny list</li><li>with several entries</li>

</ul></li><li>look: recursive lists!</li>

</ul></li>

</ul>

• UML model

QUIZ

public class PrintVisitor implements HTMLVisitor<String> {

public String visitText(Text t) { return t.getText(); }

public String visitBulletList(BulletList b) {String result = "<ul>";for (HTML h : b.getEntries())

result += "<li>"+h.accept(this)+"</li>";return result+"</ul>”;

}} How would you declare accept in interface HTML?

1. public <E> E accept(HTMLVisitor<E> v);2. public E accept(HTMLVisitor<E> v);3. public String accept(HTMLVisitor<String> v);4. public String accept(PrintVisitor v);5. I don’t know

Traversal by visitor

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

));

Easier:

Tree t = new Parser(“6+(8*2-1)”).parseExpression();

Parsing an expression

• Problem:– build the recursive data structure for

arithmetic expressions such as3 + 4 * 5

(3 + 4) * 51 – (2 – (3 – (4 – 5)))

• Precedence rules: – * and / take precedence over + and –– may overrule using parentheses ( ... )

Syntax diagram for expression

number

Syntax tree for two expressions

Mutually recursive methods

• Implement 3 methods that call each other recursivelyparseExpressionparseTermparseFactor

• An ExpressionTokenizer is used to group input in tokens. A token being a string of digits or one of "+", "-", "*", "/", "(", ")". Methods:peekTokennextToken

public class Expression Parser {public ExpressionParser(String anExpression) {

tokenizer = new ExpressionTokenizer(anExpression);}

public Tree parseExpression() { ... }

public Tree parseTerm() { ... }

public Tree parseFactor() { ... }

private ExpressionTokenizer tokenizer;}

public Tree parseExpression() {Tree t = parseTerm();while ("+".equals(tokenizer.peekToken())

|| "-".equals(tokenizer.peekToken())) {Operator op = Operator.parseOp(

tokenizer.nextToken());Tree t2 = parseTerm();t = new Node(t,op,t2);

}return t;

}

public int parseTerm() {Tree t = parseFactor();while ("*".equals(tokenizer.peekToken())

|| "/".equals(tokenizer.peekToken())) {Operator op = Operator.parseOp(

tokenizer.nextToken());Tree t2 = parseFactor();t = new Node(t,op,t2);

}return t;

}

public int parseFactor() {Tree t;if ("(".equals(tokenizer.peekToken())) {

tokenizer.nextToken();t = parseExpression();tokenizer.nextToken(); // read ")"

} elset = new Leaf(

Integer.parseInt(tokenizer.nextToken()));return t;

}

QUIZpublic Tree parseTerm() { }

if ("!".equals(tokenizer.peekToken())) {tokenizer.nextToken();return new BoolNode(

BoolOperator.NOT,parseFactor());}return parseFactor();

BoolTree t = parseFactor();if ("!".equals(tokenizer.peekToken())) {

tokenizer.nextToken();t = new BoolNode(BoolOperator.NOT,t);

}return t;

a

b

(Part of) syntax diagram for Boolean expression

Which code could replace ?

1. a2. b3. a and b4. Neither a nor b5. I don’t know

Parse Expression

top related