Trees

      A tree is an ADT that stores elements hierarchically

 

Tree definitions

      Recursive definition--A tree consists of a root and zero or more subtrees

   each subtree is a child of the root

   the root is the parent of the subtrees

   the root and parent are connected by a directed edge.

      If there are n nodes, there will be n-1 edges

      An internal node is a node that has children

      An external node or leaf is a node with no children

 

Tree terminology

   Leaf - node with no children

   Siblings - nodes with the same parent

   Path - sequence of nodes from one node to another

   Length of path - number of edges on path

   Depth - length of the path from root to a node

   Height of a tree – the number of nodes along the longest path between it root and leaves (also the number of levels in the tree)

   Depth of tree - depth of the deepest leaf equal to the height of the tree

 

General Trees

      Each node in a a tree can have an arbitrary number of children

      Sometimes trees are characterized by the maximum number of children a node can have

      The maximum number is called m; the tree is called an m-ary tree

      If m is 2, it is a binary tree;

      If m is 5, it is a 5-ary tree

 

Full m-ary trees

      A tree is called a full m-ary tree if every internal vertex has exactly m children

      Total nodes = # leaves + # internal nodes

      There are at most mh-1 leaves in an m-ary tree of height h

      Parts of an m-ary tree

   m is the number of children

   n is the total number of nodes

   i is the number of internal nodes

   L is the number of leaves

      m must always be known; once one other part is known, the other two can be found

 

Theorems of full m-ary trees
the relationship between leaves & internal nodes

      Given the number of internal nodes i

   Find the number of total nodes n = mi + 1

   Find the number of leaves L = (m-1)i+1

      Given n the total number nodes n

   Find the number of internal nodes i  = (n-1)/m

   Find the number of  leaves L = [(m-1)n +1)]/m

      Given the number of leaves L

   Find the number of total nodes n = (mL-1)/(m-1)

   Find the number of internal nodes i  = (L-1) /(m-1)

 

 

Real life problem

      Suppose someone starts a chain letter.  Each person sent the letter is asked to send it to four people.  Some people do, but others do not.

      How many people have seen the letter, including the first person, if no one receives more than one letter, and if the chain letter ends after there have been 100 people who read it, but did not send it out?

      How many people sent out the letter?

      Known: 

m = 4;     Leaves = 100

      Find:

n = how many people have seen the letter

i = How many people sent out the letter

 

Tree Traversal

      Traversing a tree means to go to each node in some sort of order

      There are several different orders you can go to (or visit) each node

      Keep in mind, that we draw trees showing only the keys

    Each key would also be associated with the value of the key-value pair

      We could say we iterate through the tree, just like we iterate through an array or a linked list

 

Ways to Traverse a Tree

      Inorder

    Recursively visit all nodes in the left subtree

    Process the root node

    Recursively visit all nodes in the right subtree

      Preorder

    Process the root node

    Recursively visit all nodes in the left subtree

    Recursively visit all nodes in the right subtree

      Postorder

    Recursively visit all nodes in the left subtree

    Recursively visit all nodes in the right subtree

    Process the root node (maybe print)

 

Traversing a tree

            inOrder(t)

            {           if(t !=null)


                 {      inOrder(t.left)

                       {           if(t !=null)

                            {      inOrder(t.left)                                                                                                  

           {           if(t !=null)

                       {           inOrder(t.left)   {      if(t !=null)  } returns false

                                                            Output t.data

                                   inOrder(t.right) {           if(t !=null)  } returns false          

                       }          

                                    }

                                   Output t.data

                                   inOrder(t.right)

           {           if(t !=null)

                       {           inOrder(t.left)   {      if(t !=null)  } returns false

                                                            Output t.data

                                   inOrder(t.right) {           if(t !=null)  } returns false

                       }          

}

                       }

    }                                        

                        Output t.data

                        inOrder(t.right)                                                            

                 {           if(t !=null)

                       {           inOrder(t.left)   {           if(t !=null)  } returns false

                             Output t.data

                              inOrder(t.right)   {        if(t !=null)  } returns false                      

                       }          

                         }


             }          

   }

 

Tree Traversal

      Traversing a tree means to go to each node in some sort of order

      There are several different orders you can go to (or visit) each node

      Keep in mind, that we draw trees showing only the keys

    Each key would also be associated with the value of the key-value pair

      We could say we iterate through the tree, just like we iterate through an array or a linked list

 

Ways to Traverse a Tree

      Inorder

    Recursively visit all nodes in the left subtree

    Process the root node

    Recursively visit all nodes in the right subtree

      Preorder

    Process the root node

    Recursively visit all nodes in the left subtree

    Recursively visit all nodes in the right subtree

      Postorder

    Recursively visit all nodes in the left subtree

    Recursively visit all nodes in the right subtree

    Process the root node (maybe print)

 

Binary Trees

      Every node has at most two children

      Types of binary trees           

   Expression trees

   Binary Search Trees

   Heaps

      As long as the tree stays balanced, the height of the tree is the log of the number of (nodes +1)

      If you have a full binary tree with 127 nodes, what is its height?

   Log 128 = 7;     27=128

 

Expression trees

      Leaves are operands (data)

      Interior nodes are operators

      Traversing an expression tree gives inorder or postorder notation

    inorder
(left, visit node, right)

    postorder
(left, right, visit node)

 

Examples of expression trees   

      Write the expression for the expression on the overhead

      Draw an expression tree for this expression
(A + B) * C + D * (E + F)/G

 

Binary Search Trees

      A BST is a a binary tree whose nodes contain Comparable objects and are ordered this way:

    The data in the left node is less than the parent

    The data in the right node is greater than the parent

      The shape of the BST depends on the order in which the data is inserted

    Always start at the root, and create a new leaf to hold the new data

    Create a BST with this data:  5 3 7 4 2 6  1 8

    Create a BST with this data:   5 4 6 3 2 7 1 8

    Create a BST with this data:   1 2 3 4 5 6 7 8

 

Put these keys into a BST

      Jane, Nancy, Bob, Tom, Wendy, Ellen, Alan

      Change the tree so that Tom is entered before Nancy.

      How many comparisons does it take to search for Henry?

      To search for Alan?   For Wendy? For Mary?

      What was the maximum number of comparisons?  What is the height of the tree?

      Do a preorder, inorder and post order traversal of the search tree.

 

Searching a BST

      As long as the tree stays balanced, a search takes O(log n) time

   If the tree is balanced, the height of the tree is (roughly) the log of the number of nodes in the tree

   Balanced is defined different ways by different algorithms

      In the worst case, a binary tree can degenerate down into a linked list

   Then a search takes O(n) time

 

Deleting from a BST

      There are three cases

    The node to be deleted has no children

    The node to be has one child

    The node to be deleted has two children

      No children – simplest case; just delete the node

      One child

    Replace the node with its child

      Two children

    The node is replaced by its inorder sucessor

    This will be the leftmost node of its right subtree

    This may cause another deletion further down the tree

 

Heaps

      A heap is a complete binary tree whose nodes contain Comparable objects and are ordered this way:

    Each node contains objects that are smaller than its parent

    So the root contains the largest object in the tree

    This is true of each subtree also

      There are two kinds of heaps:

    MaxHeap, defined above

    MinHeap, where each node contains objects that are larger than its parent

      There is no left to right ordering as in heap

 

Draw a min and max heap

      Using 25 for the root, draw a max head with 10 nodes.  Keep it balanced

      Again, using 25 for the root, draw a min heap with 10 nodes, keeping it balanced.

 

Uses of heaps

      Heaps are usually used to implement a PriorityQueue

      They are sometimes used for sorting, heapsort

   Heapsort is an O(n log n) sort, but is slower than Quicksort

   The only time it is really used in sorting is if the data is already arranged in a heap, and just needs to be sorted

 

Implementing a binary tree

The Node class

      The data members

   The classic node has two reference variables and one data object (often called the key)

Class Node
{    Object key;
       Node left, right;
}

      The operations

   Constructors, getters and setters, some Booleans

 

Adding to a BST

      First must search the tree to find the node where the new item should be added

      Then the new item must be inserted in the correct place

      To see how the iterators work, we will use reference variables to search the tree

      The new node we want to add is z

      t is pointing to the root of the tree

    Tree on board

 

Inserting into a BST pseudo code

      void add(t, z)
{      Node y = null;
        Node x = t.root;

         while(x != null)    //find the correct place
        {           y = x;
                    if( z.key < x.key) x = x.left;
                    else x = x.right;

    }   // insert the node
        if (y = null) t.root = z;
        else if (z.key < y.key) y.left = z
             else y.right = z;
}