390 likes | 498 Views
Binary Trees. Wellesley College CS230 Lecture 17 Thursday, April 5 Handout #28. PS4 due 1:30pm Tuesday, April 10. Motivation: Inefficiency of Linear Structures. Up to this point our focus has been linear structures: arrays, vectors, linked lists
E N D
Binary Trees Wellesley College CS230 Lecture 17 Thursday, April 5 Handout #28 PS4 due 1:30pm Tuesday, April 10
Motivation: Inefficiency of Linear Structures Up to this point our focus has been linear structures: arrays, vectors, linked lists Some operations on linear structures are cheap: • Constant time: Get/set elt at a given index in array/vector Add elt to the end of a vector Add elt to the front of a im/mutable list Add elt to the back of a mutable list (if have pointer to last node) • Logarithmic time:Binary search on sorted array/vector Other operations are expensive (linear in size): Inserting/deleting elt at arbitrary position in an array/vector/listFinding an element in a list (even a sorted one) There is no linear structure for which insertion, deletion, and membership operations (e.g. in priority queues, sets, bags, and tables) are all cheaper than linear.
Idea: Branching of Binary Search + Linking of Linked Lists → Binary Trees • A binary tree is either • a leaf: • a node with (1) a left subtree (2) a value and (3) a right subtree: binary tree node left subtree value right subtree
A Sample Binary Tree F F A C A C D B G D B G E E Values are often shown in the nodes Often, the leaves are not shown, but they’re still there!
Tree Terminology Nodes A and C are the children of node F; F is the parent of A and C; A and C are siblings.Grandparents, grandchildren, etc. defined similarly. A node without a parent is a root. E.g. node F is the root of the tree, and node A is the root of F’s left subtree (considered separately from the whole tree). A descendant of a node n is a node on the path from n to a leaf. E.g. nodes D, B, and E are the descendants of A. An ancestor of a node n is a node on the path from n to the root. E.g. Nodes B, A, and F are the ancestors of E. F A C D B G E
More Tree Terminology • The height of a node n is length of the longest path from n to a leaf below it. E.g., node G has height 1, node C has height 2, and node F has height 4. • The depth of a node n is the length of the path from n to the root. E.g., node F has depth 0, node C has depth 1, and node G has depth 2. • A binary tree is height-balanced iff at every node n, the heights of n’s left and right subtrees differ by no more than 1. The example tree is height-balanced, but would not be if G were removed. (There are other notions of tree balance in CS231.) F A C D B G E
Binary Search Trees To get full advantage of binary trees for data structures, need the values to be ordered. A binary search tree (BST) is a binary tree in which the following properties hold at every node: (1) All elements in the left subtree are ≤ the value; (2) All elements in the right subtree are ≥ the value. Here is a sample BST → BSTs will be very important in the next lecture, when we use binary trees to implement data structureslike sets, bags, and tables For now,we’ll stick with generic binary trees. E B F A D G C
Trees: An Omnipresent Data Representation • Family trees • File system • Sport tournaments • Animal kingdom • Organizational chart • Java class hierarchy • A graph without cycles • A home’s plumbing and electrical systems • … • A convenient data structure A tree T is a set of one or more nodes s.t. T is partitioned into two disjoint subsets: • A single node r, the root • Sets that are also trees, called subtrees of r
Arithmetic Expressions as Trees a-b a-(b/c) (a-b)*c - - * a b a / - c b c a b Arithmetic expressions are often represented as binary trees. Internal nodes are operations - Leaves are numbers/variables. Operator precedence is enforced by the tree shape.
TreeInterface public interface TreeInterface { public boolean isLeaf (); public Object getValue (); public Tree getLeft (); public Tree getRight (); public void setValue (Object newValue); public void setLeft (Tree newLeft); public void setRight (Tree newRight); public String toString (); }
Example public static void main(String[] args) { Tree T = new Tree(); T = new Tree("A", new Tree(), new Tree()); Tree tl = new Tree("B", new Tree(), new Tree()); Tree tr = new Tree("C", new Tree(), new Tree()); T.setLeft(tl); T.setRight(tr); T.getLeft().setValue(new Integer(5)); T.setRight(T.getRight().getRight()); } • Draw T’s contents . (. A .) ((. B .) A (. C .)) ((. 5 .) A (. C .)) ((. 5 .) A .)
lt value isLeaf rt Tree Implementation Contract public Tree () public Tree (Object val, Tree lt, Tree rt) public boolean isLeaf () public Object getValue () public Tree getLeft () public Tree getRight () public void setValue (Object newValue) public void setLeft (Tree newLeft) public void setRight (Tree newRight) public String toString () private Object value; private Tree lt, rt; private boolean isLeaf; “Jane” F “Sally” F “Joe” F / “” T / / “” T / / “” T / / “” T /
public class Tree implements TreeInterface { // instance variables private Object value; private Tree left, right; private boolean isLeaf; // constructors public Tree () { isLeaf = true; } public Tree (Object value, Tree lt, Tree rt) { this.value = value; this.left = lt; this.right = rt; isLeaf = false; } // instance methods public boolean isLeaf () { // returns true if the tree is a leaf (i.e. empty tree) return isLeaf; } public Object getValue () { if (isLeaf) thrownew RuntimeException ("Attempt to get value of empty tree"); else return value; } public Tree getLeft () { if (isLeaf) thrownew RuntimeException ("Attempt to get left subtree of an empty tree"); else return left; } public Tree getRight () { if (isLeaf) thrownew RuntimeException ("Attempt to get right subtree of an empty tree"); else return right; }
And the Rest... public void setValue (Object newValue){ // sets the Object in the root node of the tree to a new value if (isLeaf) thrownew RuntimeException ("Attempt to get value of empty tree"); else this.value = newValue; } public void setLeft (Tree newLeft) { // changes the left subtree to a new tree } public void setRight (Tree newRight){ // changes the right subtree to a new tree }
How Do You Print a Tree? public String toString () { // returns a String representation of the contents of a Tree } * / - 10 + 5 3 2
Ways to Visit the Nodes of a Tree public String toString () { // returns a String representation of the contents of a Tree if (this.isLeaf()) return ""; else return"(" + this.getLeft().toString() + " " + this.getValue() + " " + this.getRight().toString() + ")"; } * / - 10 + 5 3 2
Syntatic Sugar - a bunch of static’s publicstatic void setValue (Tree t, Object newValue) { t.setValue(newValue); } publicstatic void setLeft (Tree t, Tree newLeft) { t.setLeft(newLeft); } publicstatic void setRight (Tree t, Tree newRight) { t.setRight(newRight); } // using the new notation: Tree T = leaf(); T = node("A", leaf(), leaf()); Tree tl = node("B", leaf(), leaf()); Tree tr = node("C", leaf(), leaf()); setLeft(T, tl); setRight(T, tr); setValue(getLeft(T),new Integer(5)); setRight(T, getRight(getRight(T)) ); publicstatic Tree leaf () { returnnew Tree(); } publicstatic Tree node (Object val, Tree lt, Tree rt) { returnnew Tree(val, lt, rt); } publicstatic boolean isLeaf (Tree t) { return t.isLeaf; } publicstatic Object getValue(Tree t) { return t.getValue(); } publicstatic Tree getLeft(Tree t) { return t.getLeft(); } publicstatic Tree getRight(Tree t){ return t.getRight(); }
Traversal of a Binary Tree • Is a way of visiting each node in the tree • Recursive traversal algorithms • Preorder traversal • Inorder traversal • Postorder traversal 1 6 7 2 7 2 7 5 6 3 4 1 4 1 4 5 6 3 5 2 3
Three Ways to Traverse the Tree publicstatic void preOrderWrite (Tree t) { // prints contents of the tree t using preOrder traversal of the nodes if (!isLeaf(t)) { System.out.print(" " + getValue(t)); preOrderWrite(getLeft(t)); preOrderWrite(getRight(t)); } } publicstatic void inOrderWrite (Tree t) { // prints contents of the tree t using inOrder traversal of the nodes if (!isLeaf(t)) { inOrderWrite(getLeft(t)); System.out.print(" " + getValue(t)); inOrderWrite(getRight(t)); } } publicstatic void postOrderWrite (Tree t) { // prints contents of the tree t using postOrder traversal of the nodes if (!isLeaf(t)) { postOrderWrite(getLeft(t)); postOrderWrite(getRight(t)); System.out.print(" " + getValue(t)); } }
lt value isLeaf rt Tree Contract (interface + instance vars) private Tree lt; private Object value; private boolean isLeaf; private Tree rt; public Tree () public Tree (Object val, Tree lt, Tree rt) public boolean isLeaf () public Object getValue () public void setValue (Object newValue) public Tree getLeft () public void setLeft (Tree newLeft) public Tree getRight () public void setRight (Tree newRight) public String toString () “Jane” F “Sally” F “Joe” F / “” T / / “” T / / “” T / / “” T /
Syntatic Sugar publicstatic void setValue (Tree t, Object newValue) { t.setValue(newValue); } publicstatic void setLeft (Tree t, Tree newLeft) { t.setLeft(newLeft); } publicstatic void setRight (Tree t, Tree newRight) { t.setRight(newRight); } Tree T = leaf(); T = node("A", leaf(), leaf()); Tree tl = node("B", leaf(), leaf()); Tree tr = node("C", leaf(), leaf()); setLeft(T, tl); setRight(T, tr); setValue(getLeft(T),new Integer(5)); setRight(T, getRight(getRight(T)) ); publicstatic Tree leaf () { returnnew Tree(); } publicstatic Tree node (Object val, Tree lt, Tree rt) { returnnew Tree(val, lt, rt); } publicstatic boolean isLeaf (Tree t) { return t.isLeaf; } publicstatic Object getValue(Tree t) { return t.getValue(); } publicstatic Tree getLeft(Tree t) { return t.getLeft(); } publicstatic Tree getRight(Tree t){ return t.getRight(); }
Basic Operations: height() • Height of a node n is the distance from the node to its furthest child publicstatic int height (Tree t){ // returns the height of the tree t if (isLeaf(t)) return 0; else return 1 + Math.max( height(getLeft(t)), height(getRight(t))); }
Basic Operations: countNodes() publicstatic int countNodes (Tree t) { // returns the number of nodes in tree t if ( ) else }
Basic Operations: countOccurrences() • Count occurrences of S in tree T • If root contains S, it is 1 + • The number of times it occurs in the left subtree + • The number of times it occurs in the right subtree publicstatic int countOccurrences (Tree t, String S) { // returns the number of nodes in the tree t that contain // the input String S if (isLeaf(t)) return 0; else { if (((String)getValue(t)).equals(S)) return 1 + countOccurrences(getLeft(t), S) + countOccurrences(getRight(t), S); else return countOccurrences(getLeft(t), S) + countOccurrences(getRight(t), S); } } A F A A B C D A
Basic Operations: isMember() isMember() returns true iff the input word is contained somewhere in the tree publicstatic boolean isMember (String word, Tree t) { if (isLeaf(t)) return false; elseif (((String)t.getValue()).equals(word)) return true; else return(isMember(word, getLeft(t)) || isMember(word,getRight(t))); }
Helen 0 Helen Wendy 1 Nina 2 Caitlin 3 Joan Wendy Nina 4 Merideth 5 6 7 Caitlin Joan Merideth 8 Full and Complete • Full binary tree is a binary tree of height h with no missing nodes • All leaves are at level h • All internal nodes each have two children • Complete binary tree isa binary tree of height h that is full to level h – 1 and has level h filled in from left to right • Full binary => complete • There is a simpler implementation for full and complete trees
Recursive Definition of Full Binary Tree • Full binary tree • If T is empty, T is a full binary tree of height 0 • Else if T is not empty T is a full binary tree if its root’s subtrees are both full binary trees of height h – 1 publicstatic boolean isFullBT (Tree t) { if else }
Array Representation of Binary Trees A binary tree can be represented using an array of tree nodes Each tree node contains a data portion and two indexes (one for each of the node’s children) Requires the creation of a free list which keeps track of available nodes The free list is being kept inside the tree array! Allows for representation of any kind of tree, not just complete ones tree root 0 item lt rt 0 Helen 1 2 free 6 1 Wendy 3 4 2 Nina 5 -1 3 Caitlin -1 -1 4 Joan -1 -1 5 Merideth -1 -1 6 -1 7 7 -1 8 8 -1 9 … … … … Helen Wendy Nina Caitlin Joan Merideth
Basic Operations: isBalanced() A binary tree is balanced iff the height of any node’s right subtree differs by no more than 1from the height of the node’s left subtree • Complete binary trees are balanced publicstatic boolean isBalanced(Tree t) { if (isLeaf(t)) return true; else return ((Math.abs(height(getLeft(t)) - height(getRight(t))) <= 1) && (isBalanced(getLeft(t))) && (isBalanced(getRight(t)))); }
alex * joe * bo * claire * al * harry * jane * Recording the Shape of a Tree publicstatic Tree makeStarTree (Tree t) { // returns a new tree that has // the same size and shape as t, but with // all nodes in the tree containing // a String with a * character if (isLeaf(t)) return leaf(); else return node ("*", makeStarTree(getLeft(t)), makeStarTree(getRight(t))); }
alex xela joe eoj bo ob claire erialc al la harry yrrah jane enaj Applying a Function on a Tree publicstatic Tree makeReverseTree (Tree t) { // returns a new tree that is the same size // and shape as t, but with all of the // Strings labels in the tree reversed if (isLeaf(t)) return leaf(); else return node (reverseString((String)getValue(t)), makeReverseTree(getLeft(t)), makeReverseTree(getRight(t))); } publicstatic String reverseString (String S) { // returns a String that is the reverse of the input String S String newS = ""; for (int i = 0; i < S.length(); i++) newS = S.charAt(i) + newS; return newS; }
Destructive Versions publicstatic void makeStarTree2 (Tree t) { // alters the contents of the input tree so that all of the // nodes contain a String with a star character if (!(isLeaf(t))) { setValue(t, "*"); makeStarTree2(getLeft(t)); makeStarTree2(getRight(t)); } } publicstatic void makeReverseTree2 (Tree t) { // alters the contents of the input tree so that all of the // Strings in the tree are reversed if (!(isLeaf(t))) { setValue(t, reverseString((String)getValue(t))); makeReverseTree2(getLeft(t)); makeReverseTree2(getRight(t)); } }
alex joe bo claire al harry jane alex bo joe al harry claire jane The daVinci Tree ;-) publicstatic void flipTree (Tree t) { // alters the shape of tree // by changing it a mirror reversal if (!isLeaf(t)) { Tree tempTree = getLeft(t); setLeft(t, getRight(t)); setRight(t, tempTree); flipTree(getLeft(t)); flipTree(getRight(t)); } }
1 alex 2 bo 3 joe 6 al 4 harry 7 claire 13 jane The Index of an Array Representation publicstatic Tree makeLabelTree (Tree t) { // returns a new tree with the same shape // and size as the input tree, // in which the value in each node // of the new tree is the index // of the node in an array representation return labelTree(t, 1); } publicstatic Tree labelTree (Tree t, int label) { // recursive helper method of makeLabelTree() if (isLeaf(t)) return leaf(); else return node(new Integer(label), labelTree(getLeft(t), 2*label), labelTree(getRight(t), 2*label+1)); }
4 alex 2 bo 3 joe 2 al 1 harry 1 claire 1 jane makeHeightTree() publicstatic Tree makeHeightTree (Tree t) { /* returns a new tree that has the same size and shape as t, and in which the node value is the height of the tree rooted at the corresponding node of the input tree */ if (isLeaf(t)) return leaf(); else return node(new Integer(height(t)), makeHeightTree(getLeft(t)), makeHeightTree(getRight(t))); }
1 alex 2 bo 2 joe 3 al 3 harry 3 claire 4 jane makeLevelTree() publicstatic Tree makeLevelTree (Tree t) { /* returns a new tree that is the same size and shape as t, in which the value in each node of the new tree is the level of the corresponding node in the input tree */ return levelTree(t, 0); } publicstatic Tree levelTree (Tree t, int h) { // recursive helper method for makeLevelTree() if (isLeaf(t)) return leaf(); else return node(new Integer(h + 1), levelTree(getLeft(t), h + 1), levelTree(getRight(t), h + 1)); }
Binary Search Tree (BST) • A binary tree that for each node n: • n’s value is greater than all values in its left subtree TL • n’s value is less than all values in its right subtree TR • Both TL and TR are binary search trees 5 Helen 2 6 Elaine Nina 1 4 7 Caitlin Gina Merideth Wendy 3 A binary search tree of numbers A binary search tree of names
Decision Trees for Expert Systems • Welcome to the game of Twenty Questions! • Think of an animal and I will try to guess it • Does it have four legs? • yes • Does it have hooves? • no • Is it a dog? • yes • I won! • Keep playing? • yes • Think of another animal and I will try to guess it • Does it have four legs? • no • Does it swim? • no • Is it an ostrich? • no • I give up! What is your animal • me! Does it have 4 legs? no yes Does it swim? Does it have hooves? no yes no yes Is it an Ostrich? Is it a Goldfish? Is it a Dog? Is it a Cow?