420 likes | 664 Vues
Tree. 1. 2. 5. 6. 7. 3. 4. Basic characteristic. Top node = root Left and right subtree Node 1 is a parent of node 2,5,6 . Node 2 is a parent of node 3,4 == Node 3,4 are children of node 2. Node 3 and 4 are siblings. Node 1 is an ancestor of node 7.
E N D
1. 2. 5. 6. 7. 3. 4. Basic characteristic
Top node = root • Left and right subtree • Node 1 is a parent of node 2,5,6. • Node 2 is a parent of node 3,4 == • Node 3,4 are children of node 2. • Node 3 and 4 are siblings. • Node 1 is an ancestor of node 7.
Node that does not have any branch going out = leaf. In the picture, the leaves are 3, 4, 5 and 7. • Notice: there is only 1 path from a root to a node. • depth of node nis the path length from root to n. • Example: depth of node 7 is 2. • Height of n is the maximum path length from n to leaf. • Example: height of node 7 is 0. • Height of node 1 is 2.
Height of a tree = = height of its root. • If a tree only has root, we let its height be 0. For empty tree, we let its height be -1. • height of any tree = = height of its heighest subtree +1. • level of anode • A child of a node has 1 more level than its parent. • A root hasits level = = 0.
Link to next sibling. Link to its first child. 1 6 5 2 7 4 3 Data If a node can have any number of branches? • We can never be sure of the number of branches? • Preparing many branches in advance is a waste of space. • One solution! ->
How to arrange nodes for printing • preorder • Pick the root first • Then pick subtree • Within subtree, pick its root first, and so on….
1. 2. 5. 6. 7. 3. 4. Preorder result is 1,2,3,4,5,6,7 First to pick 4th, thissubtree Second, thissubtree Inside, it is alsopreorder. Inside, we also view it with preorder. Third
postorder • View all subtrees, then the root. • Inside each subtree, use postorder. • The postorder result of our example is 3,4,2,5,7,6,1. • inorder • Left subtree comes first, then root, then right subtree. • Inside each subtree, use inorder. • The inorder result of our example is (we do not count a subtree that has 5 because we do not know which side it will be on) 3,2,4,1,6,7
breadth-first search • The first 3 methods we have seen are tree-searching using depth-first search • When looking at each subtree, we must finish with the whole of that subtree before we can carry on. • breadth-first inspects a tree level by level, starting from root. • Our example tree then gives the following result. -> 1,2,5,6,3,4,7
* + - a * d e b c breadth-first implementation • When we look at a node, we record the children of that node into a queue created for storing next level nodes (next level queue). • Example: if we have
breadth-first implementation(2) • When we look at the root, we record itsildren into next level queue. Therefore, at this stage, next level queue has + and –. • this level queue = next level queue; clear next level queue • Inspect this level queue. • Find +: Now we insert the children of + into next level queue • At this stage, next level queue = a,* • Continue inspecting this level queue, • we find – :Now we insert the children of - into next level queue • At this stage, next level queue = a,*,d,e • No more member in this level queue, therefore let this level queue = next level queue. • At this stage, this level queue = a,*,d,e • Now starting with this level queue again. And so on.
Binary Tree • Each node can have at most 2 branches. • It is possible to have one branch at every level, meaning it is a linked list (skewed tree).
full binary treeorperfectly balanced tree • A complete triangle, no missing leaf.
A N E T O X complete tree • Full up to the level before the highest level. • At the highest level, leaves must fill from left to right. Full is complete, but complete is not full.
complete tree(2) • If we put members of a complete binary tree into an array, breadth-first: • Member at the i_th position will have its left child at the 2i+1 th position. • And its right child will be at 2i+2 th position. • A parent of i is at the (i-1)/2 th position (no decimal) Example: left child of E must have index = = 2*2+1 =5. It is X. The parent of E must have index == (2-1)/2 = 0
two-tree • Must beempty tree or • All non-leaf must have 2 branches.
Binary tree : Theory Let • leaves(t)be the number of leaves in the tree t. • n(t) be the number of nodes of tree t. • height(t) be the height of t. • leftsubtree(t) be the left subtree of t. • rightsubtree(t) be the right subtree of t. • max(a,b) be a maximum value from a and b.
For a non empty binary tree, we have the following relations: If t is a two-tree, then Then t is definitely a two-tree. If If t is a full tree,
If , then t is a full tree
Proving base case is when our tree has only its root. Which is true. inductive caseis when our tree has height h. Let We must prove that when t has height = h+1, then
We know that: We can substitute n(t) into our equation.
Fact about External Path length • Lett be a binary tree that has root. External Path length, E(t), is the sum of the depth of all leaves. • If t is a binary tree that has leaves(t) = k (more than 0), then
Binary Search Tree Is an empty tree or a tree that • Every member in leftsubtree(t) has smaller value than the member at the root. • Every member in rightsubtree(t) has larger value than the member at the root. • Both leftsubtree(t) and rightsubtree(t) are also binary search trees.
7 5 11 2 6 14 4 • Finding a member is easy. Let us try to find 4. When we look at each node, we know immediately which side of the tree that we should carry on looking. • Therefore the searching time only depends on the height of our tree. The height is a log of n(t).
class BinaryNode • { • // Constructors • BinaryNode( Comparable theElement ) • { • this( theElement, null, null ); • } • BinaryNode( Comparable theElement, BinaryNode lt, BinaryNode rt ) • { • element = theElement; • left = lt; • right = rt; • } • // Friendly data; accessible by other package routines • Comparable element; // The data in the node • BinaryNode left; // Left child • BinaryNode right; // Right child • }
// BinarySearchTree class // // CONSTRUCTION: with no initializer // // ******************PUBLIC OPERATIONS********************* // void insert( x ) --> Insert x // void remove( x ) --> Remove x // Comparable find( x ) --> Return item that matches x // Comparable findMin( ) --> Return smallest item // Comparable findMax( ) --> Return largest item // boolean isEmpty( ) --> Return true if empty; else false // void makeEmpty( ) --> Remove all items // void printTree( ) --> Print tree in sorted order private BinaryNode root;
public class BinarySearchTree • { • private BinaryNode root; • /** • * Construct the tree. • */ • public BinarySearchTree( ) • { • root = null; • } • /** • * Insert into the tree; duplicates are ignored. • * @param x the item to insert. • */ • public void insert( Comparable x ) • { • root = insert( x, root ); • }
/** • * Remove from the tree. Nothing is done if x is not found. • * @param x the item to remove. • */ • public void remove( Comparable x ) • { • root = remove( x, root ); • } • /** • * Find the smallest item in the tree. • * @return smallest item or null if empty. • */ • public Comparable findMin( ) • { • return elementAt( findMin( root ) ); • }
/** • * Find the largest item in the tree. • * @return the largest item of null if empty. • */ • public Comparable findMax( ) • { • return elementAt( findMax( root ) ); • } • /** • * Find an item in the tree. • * @param x the item to search for. • * @return the matching item or null if not found. • */ • public Comparable find( Comparable x ) • { • return elementAt( find( x, root ) ); • }
/** • * Make the tree logically empty. • */ • public void makeEmpty( ) • { • root = null; • } • /** • * Test if the tree is logically empty. • * @return true if empty, false otherwise. • */ • public boolean isEmpty( ) • { • return root == null; • }
/** • * Print the tree contents in sorted order. • */ • public void printTree( ) • { • if( isEmpty( ) ) • System.out.println( "Empty tree" ); • else • printTree( root ); • } • /** • * Internal method to get element field. • * @param t the node. • * @return the element field or null if t is null. • */ • private Comparable elementAt( BinaryNode t ) • { • return t == null ? null : t.element; • }
/** • * Internal method to insert into a subtree. • * @param x the item to insert. • * @param t the node that roots the tree. • * @return the new root. • */ • private BinaryNode insert( Comparable x, BinaryNode t ) • { • /* 1*/ if( t == null ) • /* 2*/ t = new BinaryNode( x, null, null ); • /* 3*/ else if( x.compareTo( t.element ) < 0 ) • /* 4*/ t.left = insert( x, t.left ); • /* 5*/ else if( x.compareTo( t.element ) > 0 ) • /* 6*/ t.right = insert( x, t.right ); • /* 7*/ else • /* 8*/ ; // Duplicate; do nothing • /* 9*/ return t; • }
/** • * Internal method to remove from a subtree. • * @param x the item to remove. • * @param t the node that roots the tree. • * @return the new root. • */ • private BinaryNode remove( Comparable x, BinaryNode t ) • { • if( t == null ) • return t; // Item not found; do nothing • if( x.compareTo( t.element ) < 0 ) • t.left = remove( x, t.left ); • else if( x.compareTo( t.element ) > 0 ) • t.right = remove( x, t.right ); • else if( t.left != null && t.right != null ) // Two children • { • t.element = findMin( t.right ).element; • t.right = remove( t.element, t.right ); • } • else • t = ( t.left != null ) ? t.left : t.right; • return t; • }
X y y y Replacing a deleted element with the smallest value of its right subtree.
x y y Replacing a deleted node with its subtree. This happens when the node only has one subtree.
/** • * Internal method to find the smallest item in a subtree. • * @param t the node that roots the tree. • * @return node containing the smallest item. • */ • private BinaryNode findMin( BinaryNode t ) • { • if( t == null ) • return null; • else if( t.left == null ) • return t; • return findMin( t.left ); • }
/** • * Internal method to find the largest item in a subtree. • * @param t the node that roots the tree. • * @return node containing the largest item. • */ • private BinaryNode findMax( BinaryNode t ) • { • if( t != null ) • while( t.right != null ) • t = t.right; • return t; • }
/** • * Internal method to find an item in a subtree. • * @param x is item to search for. • * @param t the node that roots the tree. • * @return node containing the matched item. • */ • private BinaryNode find( Comparable x, BinaryNode t ) • { • if( t == null ) • return null; • if( x.compareTo( t.element ) < 0 ) • return find( x, t.left ); • else if( x.compareTo( t.element ) > 0 ) • return find( x, t.right ); • else • return t; // Match • }
/** • * Internal method to print a subtree in sorted order. • * @param t the node that roots the tree. • */ • private void printTree( BinaryNode t ) • { • if( t != null ) • { • printTree( t.left ); • System.out.println( t.element ); • printTree( t.right ); • } • }
// Test program • public static void main( String [ ] args ) • { • BinarySearchTree t = new BinarySearchTree( ); • final int NUMS = 4000; • final int GAP = 37; • System.out.println( "Checking... (no more output means success)" ); • for( int i = GAP; i != 0; i = ( i + GAP ) % NUMS ) • t.insert( new MyInteger( i ) ); • for( int i = 1; i < NUMS; i+= 2 ) • t.remove( new MyInteger( i ) );
if( NUMS < 40 ) • t.printTree( ); • if( ((MyInteger)(t.findMin( ))).intValue( ) != 2 || • ((MyInteger)(t.findMax( ))).intValue( ) != NUMS - 2 ) • System.out.println( "FindMin or FindMax error!" ); • for( int i = 2; i < NUMS; i+=2 ) • if( ((MyInteger)(t.find( new MyInteger( i ) ))).intValue( ) != i ) • System.out.println( "Find error1!" ); • for( int i = 1; i < NUMS; i+=2 ) • { • if( t.find( new MyInteger( i ) ) != null ) • System.out.println( "Find error2!" ); • } • } • }