|
Comp202: Principles of Object-Oriented Programming II
|
Consider the following binary tree.
1
/
\
2
3
/ \
\
4 5
6
/
7
The breadth first traversal from left to right consists of visiting the nodes: 1, 2, 3, 4, 5, 6, 7 in this order. To traverse the tree in this manner, each time we visit a non-empty node, we need to save its two children in a FIFO queue, process the current node, then go through the queue and process each node in the queue in the same manner. Here is the code for printing a tree in breadth-first order.
package brs.visitor;
import brs.*; import rac.*;
/** * Prints the tree nodes in breadth traversal. * Uses a FIFO queue. * @author DXN */ public class BreadthPrint implements IVisitor {
private IRAContainer _queue = new LRSQueueFactory().makeRAC();
// IRAContainer visitor to go through the queue and process each tree // in the queus with a given BiTree visitor. private IRACVisitor _processQ = new IRACVisitor() { public Object emptyCase(IRAContainer q, Object treeVis) { return null; } public Object nonEmptyCase(IRAContainer q, Object treeVis) { ((BiTree)q.get()).execute((IVisitor)treeVis, null); return q.execute(this, treeVis); } };
/** * Nothing to print here. */ public Object emptyCase(BiTree host, Object nu) { return null; }
/** * Prints the root data, saves the left and right subtrees in _queue * and "process" _queue. */ public Object nonEmptyCase(BiTree host, Object nu) { _queue.put(host.getLeftSubTree()); _queue.put(host.getRightSubTree()); System.out.print(host.getRootDat()); return _queue.execute(_processQ, new IVisitor() { public Object emptyCase(BiTree h, Object nu) { return null; } public Object nonEmptyCase(final BiTree h, Object nu) { _queue.put(h.getLeftSubTree()); _queue.put(h.getRightSubTree()); System.out.print(" " + h.getRootDat()); return null; } }); } /** * Simple test code. */ public static void main(String[] args) { BiTree t0 = new BiTree(); t0.insertRoot(new Integer(1)); BiTree t1 = new BiTree(); t1.insertRoot(new Integer(2)); BiTree t2 = new BiTree(); t2.insertRoot(new Integer(3)); t0.setLeftSubTree(t1); t0.setRightSubTree(t2); t1.getLeftSubTree().insertRoot(new Integer(4)); t1.getLeftSubTree().getRightSubTree().insertRoot(new Integer(6)); t2.getRightSubTree().insertRoot(new Integer(5)); t2.getRightSubTree().getLeftSubTree().insertRoot(new Integer(7)); System.out.println("t0 is: \n" + t0 + "\n"); System.out.println("Breadth first traversal:"); t0.execute(new BreadthPrint(), null); System.out.println("\nDone!"); } }
What is the abstract processing here? Use a lambda where you see System.out.println. Here is the code for the invariant breadth-first tree traversal, where the variant is simply a lambda.
package brs.visitor;
import brs.*; import rac.*; import fp.*;
/** * Processes the tree nodes via breadth-first traversal. * Uses a FIFO queue. * @author DXN */ public class BreadthFirst implements IVisitor {
private IRAContainer _queue = new LRSQueueFactory().makeRAC(); private ILambda _f; private Object _acc; // accumulated result. // IRAContainer visitor to go through the queue and process each tree // in the queus with a given BiTree visitor. private IRACVisitor _processQ = new IRACVisitor() { public Object emptyCase(IRAContainer q, Object treeVis) { return _acc; } public Object nonEmptyCase(IRAContainer q, Object treeVis) { ((BiTree)q.get()).execute((IVisitor)treeVis, null); return q.execute(this, treeVis); } };
public BreadthFirst(ILambda f) { _f = f; }
/** */ public Object emptyCase(BiTree host, Object b) { return b; }
/** * Processes the root data, saves the left and right subtrees in _queue * and "process" _queue. */ public Object nonEmptyCase(BiTree host, final Object b) { _queue.put(host.getLeftSubTree()); _queue.put(host.getRightSubTree()); _acc = _f.apply(host, b); return _queue.execute(_processQ, new IVisitor() { public Object emptyCase(BiTree h, Object nu) { return b; // anything, _acc ok too. } public Object nonEmptyCase(final BiTree h, Object nu) { _queue.put(h.getLeftSubTree()); _queue.put(h.getRightSubTree()); _acc = _f.apply(h, _acc); return _acc; } }); }
/** * Simple test code. */ public static void main(String[] args) { BiTree t0 = new BiTree(); t0.insertRoot(new Integer(1)); BiTree t1 = new BiTree(); t1.insertRoot(new Integer(2)); BiTree t2 = new BiTree(); t2.insertRoot(new Integer(3)); t0.setLeftSubTree(t1); t0.setRightSubTree(t2); t1.getLeftSubTree().insertRoot(new Integer(4)); t1.getLeftSubTree().getRightSubTree().insertRoot(new Integer(6)); t2.getRightSubTree().insertRoot(new Integer(5)); t2.getRightSubTree().getLeftSubTree().insertRoot(new Integer(7)); System.out.println("t0 is: \n" + t0 + "\n"); System.out.println("Breadth first printing:"); ILambda print = new ILambda() { public Object apply(Object... args) { System.out.print("" + args[1] + ((BiTree)args[0]).getRootDat()); return " "; } }; t0.execute(new BreadthFirst(print), "");
System.out.println("\nBreadth first adding:"); ILambda add= new ILambda() { public Object apply(Object... args) { return (Integer)args[1] + (Integer)((BiTree)args[0]).getRootDat(); } }; System.out.println(t0.execute(new BreadthFirst(add), 0)); System.out.println("\nDone!"); } }
Last Revised Thursday, 03-Jun-2010 09:52:33 CDT
©2007 Stephen Wong and Dung Nguyen