410 likes | 562 Views
COSC2007 Data Structures II. Chapter 11 Trees II. Topics. ADT Binary Tree (BT) Operations Tree traversal BT Implementation Array-based LL-based Expression Notation and Tree traversal. ADT Binary Tree. A. B. C. D. E. F. G. root. H. L. I. J. K. BT Traversal.
E N D
COSC2007 Data Structures II Chapter 11 Trees II
Topics • ADT Binary Tree (BT) • Operations • Tree traversal • BT Implementation • Array-based • LL-based • Expression Notation and Tree traversal
A B C D E F G root H L I J K BT Traversal • Suppose I wanted to ‘visit’ all the nodes in this tree. • Furthermore, suppose I wanted to perform some operation on the data there (such as printing it out). • What are some of the possible visitation patterns we could use?
BT Traversal • Visit every node in a BT exactly once. • Each visit performs the same operations on each node • Natural traversal orders: • Pre-order • Node-Left-Right (NLR) • In-order • Left-Node-Right (LNR) • Post-order • Left-Right-Node (LRN)
A B C D E F G root H L I J K Pre-order Traversal • Each node is processed the first time it is observed. i.e. before any node in either subtree. • A Possible Pattern • Visit Root Node • Visit Left subtree in preorder • Visit Right subtree • Must be applied at all levels of the tree. 1 2 9 3 6 10 11 4 5 7 8 12 • Called an PreOrder Traversal
Pre-order Traversal • Pseudocode preorder (binaryTree:BinaryTree ) // Traverses the binary tree binaryTree in preorder. // Assumes that “visit a node” means to display the node’s data item if (binaryTree is not empty ) { Display the data in the root of binaryTree preorder ( Left subtree of binaryTree ’s root ) preorder ( Right subtree of binaryTree’s root ) }
A B C D E F G 8 root H L I J K 4 10 2 6 9 11 1 3 5 7 12 In-order Traversal • Each node is processed the second time it is observed. i.e. after all the nodes in its left subtree but before any of the nodes in its right subtree. • A Possible Pattern • Visit Left subtree • Visit Root node • Visit Right subtree • Must be applied at all levels of the tree.
In-order Traversal • Pseudocode inorder (binaryTree:BinaryTree ) // Traverses the binary tree binaryTree in inorder. // Assumes that “visit a node” means to display the node’s data item if (binaryTree is not empty ) { inorder ( Left subtree of binaryTree ’s root ) Display the data in the root of binaryTree inorder ( Right subtree of binaryTree’s root ) }
A B C D E F G root H L I J K Post-order Traversal • Each node is processed the third time it is observed. i.e. after all nodes in both of its subtrees. • A Possible Pattern • Visit Left subtree • Visit Right subtree • Visit Root Node • Must be applied at all levels of the tree. 12 7 11 3 6 8 10 1 2 4 5 9 H I D J K E B F L G C A
Post-order Traversal • Pseudocode postorder (binaryTree:BinaryTree ) // Traverses the binary tree binaryTree in postorder. // Assumes that “visit a node” means to display the node’s data item if (binaryTree is not empty ) { postorder ( Left subtree of binaryTree ’s root ) postorder ( Right subtree of binaryTree’s root ) Display the data in the root of binaryTree }
Implementation of BT • Possible Implementations: • Array based • Fast access • Difficult to change • Used if elements are not modified often • Reference (Pointer) based • Slower • Easy to modify • More flexible when elements are modified often
James Tony Bob Adam Davis Neil BT Array-Based Implementation • Nodes: • A Java Node class • Each node should contain: • Data portion • Left-child index • Right-child index • Tree: • Array of structures • For empty tree • index?
BT Array-Based Implementation public class TreeNode // node in the tree { private Object item ; // data item in the tree private int leftChild; // index to left child private int rightChild; // index to right child ……. //constructor } // end of TreeNode public abstract class BinaryTreeArrayedBased { protected final int MAX_NODES =100; protected TreeNode tree []; protected int root; // index of root protected int free; // index of next unused array location ……..//constructor and methods } // end BinaryTreeArrayedBased
BT Array-Based Implementation • Array based is only good for complete tree • Since tree is complete, it maps nicely onto an array representation. A C B F G D E H I J K L last A B C D E F G H I J K L T: 0 1 2 3 4 5 6 7 8 9 10 11 12
James Tony Bob 0 1 2 3 4 5 6 James Bob Adam Davis Neil Tony Adams David Neil BT Array-Based Implementation • For Complete Trees: • A formula can be used to find the location of any node in the tree Lchild ( Tree [ i ] ) = Tree [ 2 * i + 1 ] Rchild ( Tree [ i ] ) = Tree [ 2 * i + 2 ] Parent (Tree [ i ] ) = Tree [ ( i - 1) / 2 ]
Reference-Based Implementation • Typical for implementing BTs • Only the pointer to the root of the tree can be accessed by BT class clients • The data structure would be private data member of a class of binary trees
Reference -Based Implementation public class TreeNode // node in the tree { private Object item; // data portion private TreeNode leftChildPtr; // pointer to left child private TreeNode rightChildPtr; // pointer to right child TreeNode() {}; TreeNode(Object nodeItem, TreeNode left , TreeNode right ) { } ……. } // end TreeNode class
Reference -Based Implementation public abstract class BinaryTreeBasis { protected TreeNode root; ……. // constructor and methods } // end BinaryTreeBasis class • If the tree is empty, then root is ? • The root of a nonempty BT has a left subtree and right subtree, each is BT • root.getRight () • root.getLeft()
Root Item LChildPtr RChildPtr Root of right child subtree Root of left child subtree Reference -Based Implementation • Example:
The TreeNode Class publicclass TreeNode { private Object item; private TreeNode leftChild; private TreeNode rightChild; public TreeNode() {} //Constructors public TreeNode(Object myElement) { item = myElement; leftChild = null; rightChild = null; } public TreeNode(Object newItem, TreeNode left, TreeNode right){ item = newItem; leftChild = left; rightChild = right; }
TreeNode, cont'd. public Object getItem() { return item;} publicvoid setItem(Object newItem) {item = newItem;} publicvoid setLeft(TreeNode left) { leftChild = left;} public TreeNode getLeft() { return leftChild;} publicvoid setRight(TreeNode right) { rightChild = right;} public TreeNode getRight() { return rightChild;} }
TreeException public class TreeException extends RuntimeException { public TreeException(String s) { super (s); } } // end TreeException
The BinaryTreeBasis class publicabstract class BinaryTreeBasis { protected TreeNode root; public BinaryTreeBasis () { root = null; } //end constructor public BinaryTreeBasis (object rootItem) { root = new TreeNode (rootItem, null, null); } //end constructor publicboolean isEmpty() { //true is tree is empty return root == null; } publicvoid makeEmpty() { //sets root of tree to null root =null; }
1 t: The BinaryTreeBasis class public Object getRootItem() throws TreeException { if (root == null) throw new TreeException (“ Empty tree”); else return root.getItem(); } //end getRootItem() public TreeNode getRoot() { return root; } //end getRoot() } //end class BinaryTreeBasis
1 t: The BinaryTree Class publicclass BinaryTree extends BinaryTreeBasis { //the Constructors public BinaryTree() {} public BinaryTree(Object rootItem) { super (rootItem); } //end constructor public BinaryTree(Object rootItem, BinaryTree leftTree, BinaryTree rightTree) { root = new TreeNode(rootItem, null, null); attachLeftSubTree (leftTree); attachRightSubTree (rightTree); } // end constructor ••••••••all the methods go here } //end BinaryTree
2 tree: 4 5 The BinaryTree Class public void setRootItem(Object newItem) { if (root == null) root = new TreeNode (newItem, null, null); else root.setItem(newItem); } //end setRootItem
1 t 1 2 3 t: The BinaryTree Class public void attachLeft(Object newItem) { if (!isEmpty() && root.getLeft() == null) root.setLeft(new TreeNode(newItem, null, null)); } // end attachLeft public void attachRight(Object newItem) { if (!isEmpty() && root.getRight() == null) root.setRight(new TreeNode(newItem, null, null)); } // end attachRight
2 2 t: 1 4 4 5 5 t: 3 tree1: 6 7 8 3 6 7 8 The BinaryTree Class public void attachLeftSubtree(BinaryTree leftTree) throws TreeException { if (isEmpty()) throw new TreeException("Cannot attach left subtree to empty tree."); else if (root.getLeft() != null) throw new TreeException("Cannot overwrite left subtree."); else { //no empty tree, no left child root.setLeft(leftTree.root); leftTree.makeEmpty(); } //end attachLeftSubtree }
The BinaryTree Class public void attachRightSubtree(BinaryTree rightTree) throws TreeException { if (isEmpty()) throw new TreeException("Cannot attach left subtree to empty tree."); else if (root.getRight() != null) throw new TreeException("Cannot overwrite right subtree."); else { //no empty tree, no right child root.setRight(rightTree.root); rightTree.makeEmpty(); } //end attachRightSubtree }
The BinaryTree Class protected BinaryTree (TreeNode rootNode) { root = rootNode } //end constructor public BinaryTree detachLeftSubtree() throws TreeException { if (isEmpty()) throw new TreeException("Cannot detach empty tree."); else { // create a tree points to the leftsubtree BinaryTree leftTree; leftTree = new BinaryTree (root.getLeft()); root.setLeft (null); return leftTree; } } //end detachLeftSubtree }
The BinaryTree Class public BinaryTree detachRightSubtree() throws TreeException { if (isEmpty()) throw new TreeException("Cannot detach empty tree."); else { // create a tree points to the rightsubtree BinaryTree rightTree; rightTree = new BinaryTree (root.getRight()); root.setRight (null); return rightTree; } } //end detachRightSubtree }
2 1 4 5 t: 3 6 7 8 preOrderPrint( ) publicvoid preOrderPrint(TreeNode rootNode) throws TreeException { if (rootNode!=null) { System.out.print(rootNode.getItem() + " "); preOrderPrint(rootNode.getLeft()); preOrderPrint(rootNode.getRight()); } } Print tree using preorder traversal: 1 2 4 5 3 6 7 8
2 1 4 5 t: 3 6 7 8 inOrderPrint() publicvoid inOrderPrint(TreeNode rootNode) throws TreeException { if (rootNode!=null) { inOrderPrint(rootNode.getLeft()); System.out.print(rootNode.getItem() + " "); inOrderPrint(rootNode.getRight()); } } Print tree using inorder traversal: 4 2 5 1 7 6 8 3
2 1 4 5 t: 3 6 7 8 postOrderPrint( ) publicvoid postOrderPrint(TreeNode rootNode) throws TreeException { if (rootNode!=null) { postOrderPrint(rootNode.getLeft()); postOrderPrint(rootNode.getRight()); System.out.print(rootNode.getItem() + " "); } } Print tree using postOrder traversal: 4 5 2 7 8 6 3 1
2 tree1: 1 4 5 t: An Example Program publicclass BinaryTreeTest { publicstaticvoid main (String args[]) throws BinaryTreeException { BinaryTree t = new BinaryTree(newInteger(1)); System.out.println("Element at root of tree = " + t.getRootElement()); System.out.println("Initial tree is: "); t.preOrderPrint(t.getRoot()); System.out.println(); BinaryTree tree1 = new BinaryTree(newInteger(2)); tree1.attachLeft(newInteger(4)); tree1.attachRight(newInteger(5)); System.out.println("Tree1 is: "); tree1.preOrderPrint(tree1.getRoot()); System.out.println();
2 6 tree2: 1 7 4 5 8 t: 3 tree3: 6 7 8 3 6 7 8 Example, cont'd. BinaryTree tree2 = new BinaryTree(newInteger(6)); tree2.attachLeft(newInteger(7)); tree2.attachRight(newInteger(8)); System.out.println("tree2 is: "); tree2.preOrderPrint(tree2.getRoot()); System.out.println(); BinaryTree tree3 = new BinaryTree(newInteger(3)); tree3.attachLeftSubtree(tree2); System.out.println("Tree3 is: "); tree3.preOrderPrint(tree3.getRoot()); System.out.println(); t.attachLeftSubtree(tree1); t.attachRightSubtree(tree3); System.out.println("Final tree is: "); t.preOrderPrint(t.getRoot()); System.out.println(); } }
+ 5 * 6 - 8 6 Expression Tree • Given a math expression, there exists a unique corresponding expression tree. 5+ (6* (8-6))
/ * + e f + - a b c d Preorder Of Expression Tree / * + a b - c d + e f Gives prefix form of expression!
/ * + e f + - a b c d a + b * c - d / e + f Inorder Of Expression Tree Gives infix form of expression (sans parentheses)!
/ * + e f + - a b c d Postorder Of Expression Tree a b + c d - * e f + / Gives postfix form of expression!