Title: Trees
1Trees
2Graphs
- List and trees belong to a broader set of
structures called graphs - G (V,E)
- V vertex set
- E edge set
3Graphs
- What graph is represented by this linked list?
- A -- B -- C -- D -- E
4Graphs
- What graph is represented by this linked list?
- A -- B -- C -- D -- E
- G (V,E)
- V A, B, C, D, E
- E , , ,
5Digraphs
- Graphs can either be directed (digraph) or
undirected. - A B C - undirected
- A --- B --- C - undirected
- A C - directed
- We will restrict the remainder of our discussion
to digraphs.
6Representing digraphs
- We represented our digraph with a linked list
structure. - We can also represent a digraph with an incidence
matrix.
7What is the underlying graph for this doubly
linked list?
8What is the underlying graph for this doubly
linked list?
- A B C D E
- G (V,E)
- V A, B, C, D, E
- E , , , , , ,
, - What is the corresponding incidence matrix?
9What is the underlying graph for this doubly
linked list?
10Is that all there is (i.e., singly linked or
doubly linked lists)?
- A B C D E
- Note that we can have one link per node.
11Trees
- Special node called the root node.
- Appears at top of tree by convention.
- Terminal nodes are called leaf nodes.
- A special type of graph called a tree (AKA
arborescence) digraph w/ exactly 1 path from
root to all other nodes. - A set of trees is called a forest.
- Arity max branching factor per node
- Arity of 2 is called a binary tree
12Tree example
root node
Subtree rooted at node E.
13Representing trees
Can we represent the tree with an incidence
matrix?
14Representing trees
15Representing trees
left link
right link
How can we represent a tree as a linked structure?
16Representing trees
public class MyTree private class Node int
mData Node mLeft Node mRight private
Node mRoot
17Visiting nodes in a tree
- There are 3 ways do visit (process) the nodes in
a tree preorder, inorder, and postorder. - Preorder
- Process data in current node
- Process left subtree
- Process right subtree
- An example of a recursive definition
18Visiting nodes in a tree
- Inorder
- Process left subtree
- Process data in current node
- Process right subtree
- An example of a recursive definition
19Visiting nodes in a tree
- Postorder
- Process left subtree
- Process right subtree
- Process data in current node
- An example of a recursive definition
20Representing trees
- Preorder
- Process data in current node
- Process left subtree
- Process right subtree
Preorder A B D G E H I C F
21Representing trees
- Inorder
- Process left subtree
- Process data in current node
- Process right subtree
Inorder G D B H E I A F C
22Representing trees
- Postorder
- Process left subtree
- Process right subtree
- Process data in current node
Postorder G D H I E B F C A
23Trees?
- G (V,E) where
- V and E?
- VA and E?
- VA and E?
- VA,B and E?
- VA,B,C and E , ?
- VA,B,C and E , ?
- VA,B,C,D and E , ?
- VA,B,C,D,E and E ,, ?
24Binary Search Trees (BST)
- For every subtree rooted at some node n w/ value
v, all elements to the left are less than v and
all elements to the right are greater than v.
25BST example
26BST example
27BST example
28Operations on BSTs
- Search/find/contains
- Add
- Remove
- class Node
- int mData
- Node mLeft null
- Node mRight null
- Node ( int value ) mData value
29Operations on BSTs
- class MyBST
- private Node mRoot null
- public boolean contains ( int value )
-
-
30Operations on BSTs
- class MyBST
- private Node mRoot null
- public boolean contains ( int value )
- Node n mRoot
- while (n!null)
- if (n.mDatavalue) return true
- else if (value
- else n n.mRight
-
- return false
-
31Operations on BSTs
- class MyBST
- private Node mRoot null
- public boolean containsRecursive ( int value )
-
-
32Operations on BSTs
- class MyBST
- private Node mRoot null
- public boolean containsRecursive ( int value )
- return containsRecursive( value, mRoot )
-
- public boolean containsRecursive ( int value,
Node n ) -
-
-
Specifies the subtree to search.
33Begin recursion review
34n! (n factorial)
- The number of ways n objects can be permuted
(arranged). - For example, consider 3 things, A, B, and C.
- 3! 6
- ABC
- ACB
- CAB
- CBA
- BCA
- BAC
- The first few factorials for n0, 1, 2, ... are
1, 1, 2, 6, 24, 120, ...
35n! (n factorial)
- n! for some non negative integer n is defined as
- n! n (n-1) (n-2) 2 1
- 0! is defined as 1.
- From http//mathworld.wolfram.com/Factorial.html
36n! (n factorial)
- n! for some non negative integer n can be
rewritten as - 0! 1 for n 0
- 1! 1 for n 1
- n! n (n-1)! for all other n 1
37Triangular numbers
- The triangular number Tn can be represented in
the form of a triangular grid of points where the
first row contains a single element and each
subsequent row contains one more element than the
previous one. The triangular numbers are
therefore 1, 12, 123, 1234, ..., so the
first few triangle numbers are 1, 3, 6, 10, 15,
21, ...
38Triangular numbers
- which can also be expressed as
- Tn 1 for n 1
- Tn n Tn-1 for n 1
- From http//mathworld.wolfram.com/TriangularNumber
.html
39Triangular numbers
- A plot of the first few triangular numbers
represented as a sequence of binary bits is shown
below. The top portion shows T1 to T255, and the
bottom shows the next 510 values.
40Fibonacci numbers
- The sequence of Fibonacci numbers begins 1, 1,
2, 3, 5, 8, 13, 21, 34, 55, 89 ...
41Back to n! (n factorial)
- n! for some non negative integer n can be
rewritten as - 0! 1 for n 0
- 1! 1 for n 1
- n! n (n-1)! for all other n 1
base cases inductive case
42Lets code n! (n factorial)
- n! for some non negative integer n can be
rewritten as - 0! 1 for n 0
- 1! 1 for n 1
- n! n (n-1)! for all other n 1
- public static int nFactorial ( int n )
-
base cases inductive case
43Lets code n! (n factorial)
- n! for some non negative integer n can be
rewritten as - 0! 1 for n 0
- 1! 1 for n 1
- n! n (n-1)! for all other n 1
- public static int nFactorial ( int n )
- //base cases
- if (n0) return 1
-
base cases inductive case
44Lets code n! (n factorial)
- n! for some non negative integer n can be
rewritten as - 0! 1 for n 0
- 1! 1 for n 1
- n! n (n-1)! for all other n 1
- public static int nFactorial ( int n )
- //base cases
- if (n0) return 1
- if (n1) return 1
-
base cases inductive case
45Lets code n! (n factorial)
- n! for some non negative integer n can be
rewritten as - 0! 1 for n 0
- 1! 1 for n 1
- n! n (n-1)! for all other n 1
- public static int nFactorial ( int n )
- //base cases
- if (n0) return 1
- if (n1) return 1
- return n nFactorial( n-1 )
-
base cases inductive case
46Lets code n! (n factorial)
- n! for some non negative integer n can be
rewritten as - 0! 1 for n 0
- 1! 1 for n 1
- n! n (n-1)! for all other n 1
- public static int nFactorial ( int n )
- //base cases
- if (n0) return 1
- if (n1) return 1
- return n nFactorial( n-1 )
-
This is an example of a recursive function (a
function that calls itself)! To use this
function int result nFactorial( 10 )
47Back to Triangular numbers
- Tn 1 for n 1
- Tn n Tn-1 for n 1
- What is the base case(s)?
- What is the inductive case?
- How can we write the code for this?
48Back to Fibonacci numbers
- The sequence of Fibonacci numbers begins 1, 1,
2, 3, 5, 8, 13, 21, 34, 55, 89 ...
What is the base case(s)? What is the inductive
case? How can we code this?
49A note regarding recursion . . .
- Calculations such as factorial, Fibonacci
numbers, etc. are fine for introducing the idea
of recursion. - But the real power of recursion (IMHO) is in
traversing advanced data structures such as trees
(covered in more advanced classes and used in
such as applications as language parsing, games,
etc.).
50End recursion review
51Recursion
- When a function calls itself.
- If unrestricted, this will go on forever.
- Base case(s)
- Restriction(s) to avoid forever
- Typically what we should do when the value is
null, 1, 0, the first value, and/or the last
value. - Recursive case(s)
- Actual recursive function call
52Operations on BSTs
- class MyBST
- private Node mRoot null
- public boolean containsRecursive ( int value )
- return containsRecursive( value, mRoot )
-
- public boolean containsRecursive ( int value,
Node n ) -
- //base case(s)
-
-
Base case What should we do when n is null?
53Operations on BSTs
- class MyBST
- private Node mRoot null
- public boolean containsRecursive ( int value )
- return containsRecursive( value, mRoot )
-
- public boolean containsRecursive ( int value,
Node n ) -
- //base case(s)
- if (nnull) return false
-
-
54Operations on BSTs
- class MyBST
- private Node mRoot null
- public boolean containsRecursive ( int value )
- return containsRecursive( value, mRoot )
-
- public boolean containsRecursive ( int value,
Node n ) -
- //base case(s)
- if (nnull) return false
-
-
Base case What should we do if we find the
value?
55Operations on BSTs
- class MyBST
- private Node mRoot null
- public boolean containsRecursive ( int value )
- return containsRecursive( value, mRoot )
-
- public boolean containsRecursive ( int value,
Node n ) -
- //base case(s)
- if (nnull) return false
- if (n.mDatavalue) return true
-
-
56Operations on BSTs
Recursive case What should we do if value is
less than n.mData? (Where will the data have to
be then?)
- class MyBST
- private Node mRoot null
- public boolean containsRecursive ( int value )
- return containsRecursive( value, mRoot )
-
- public boolean containsRecursive ( int value,
Node n ) -
- //base case(s)
- if (nnull) return false
- if (n.mDatavalue) return true
-
-
57Operations on BSTs
- class MyBST
- private Node mRoot null
- public boolean containsRecursive ( int value )
- return containsRecursive( value, mRoot )
-
- public boolean containsRecursive ( int value,
Node n ) -
- //base case(s)
- if (nnull) return false
- if (n.mDatavalue) return true
- //recursive case(s)
- if (value
- return containsRecursive( value, n.mLeft )
-
-
58Operations on BSTs
Recursive case What remains?
- class MyBST
- private Node mRoot null
- public boolean containsRecursive ( int value )
- return containsRecursive( value, mRoot )
-
- public boolean containsRecursive ( int value,
Node n ) -
- //base case(s)
- if (nnull) return false
- if (n.mDatavalue) return true
- //recursive case(s)
- if (value
- return containsRecursive( value, n.mLeft )
-
-
59Operations on BSTs
- class MyBST
- private Node mRoot null
- public boolean containsRecursive ( int value )
- return containsRecursive( value, mRoot )
-
- public boolean containsRecursive ( int value,
Node n ) -
- //base case(s)
- if (nnull) return false
- if (n.mDatavalue) return true
- //recursive case(s)
- if (value
- return containsRecursive( value, n.mLeft )
- return containsRecursive( value, n.mRight )
-
60Operations on BSTs
- containsRecursive isnt really any better than
contains. - So one may question the value of recursion.
- Consider a toString method for a BST that returns
a string of all of the values of mData in order. - With recursion, this is trivial.
- Without recursion, this is extremely difficult.
61Recursive toString method for BSTs
- Inorder
- Process left subtree
- Process data in current node
- Process right subtree
62Recursive toString method for BSTs
- class MyBST
- private Node mRoot null
- public String toString ( )
- return toString( mRoot )
-
- //Inorder Process left subtree
- // Process data in current node
- // Process right subtree
- public String toString ( Node n )
- //base case(s)
-
- //recursive case(s)
-
63Recursive toString method for BSTs
- class MyBST
- private Node mRoot null
- public String toString ( )
- return toString( mRoot )
-
- //Inorder Process left subtree
- // Process data in current node
- // Process right subtree
- public String toString ( Node n )
- //base case(s)
-
- //recursive case(s)
-
What is the base case(s)?
64Recursive toString method for BSTs
- class MyBST
- private Node mRoot null
- public String toString ( )
- return toString( mRoot )
-
- //Inorder Process left subtree
- // Process data in current node
- // Process right subtree
- public String toString ( Node n )
- //base case(s)
- if (nnull) return
- //recursive case(s)
-
65Recursive toString method for BSTs
- class MyBST
- private Node mRoot null
- public String toString ( )
- return toString( mRoot )
-
- //Inorder Process left subtree
- // Process data in current node
- // Process right subtree
- public String toString ( Node n )
- //base case(s)
- if (nnull) return
- //recursive case(s)
-
What is the recursive case(s)?
66Recursive toString method for BSTs
- class MyBST
- private Node mRoot null
- public String toString ( )
- return toString( mRoot )
-
- //Inorder Process left subtree
- // Process data in current node
- // Process right subtree
- public String toString ( Node n )
- //base case(s)
- if (nnull) return
- //recursive case(s)
- return toString( n.mLeft ) n.mData
toString( n.mRight ) -
67Recursive toString method for BSTs
- class MyBST
- private Node mRoot null
- public String toString ( )
- return toString( mRoot )
-
- //Inorder Process left subtree
- // Process data in current node
- // Process right subtree
- public String toString ( Node n )
- //base case(s)
- if (nnull) return
- //recursive case(s)
- return toString( n.mLeft ) n.mData
toString( n.mRight ) -
Try to do this w/out using recursion!
68Recursive toString method for BSTs
Modify this to 1. have just one node per line
2. be preorder 3. indent each line according
to depth of node in tree This represents the
structure of our tree (sideways).
- class MyBST
- private Node mRoot null
- public String toString ( )
- return toString( mRoot )
-
- //Inorder Process left subtree
- // Process data in current node
- // Process right subtree
- public String toString ( Node n )
- //base case(s)
- if (nnull) return
- //recursive case(s)
- return toString( n.mLeft ) n.mData
toString( n.mRight ) -
69Remaining BST operations
70Add -52 where?
71Add -52 where?
- 10
- 5 15
- 1 7 11 62
- -52 40 70
72Add 6 where?
73Add 6 where?
- 10
- 5 15
- 1 7 11 62
- 6 40 70
74Add 13 where?
75Add 13 where?
- 10
- 5 15
- 1 7 11 62
- 13 40 70
76Add 43 where?
77Add 43 where?
- 10
- 5 15
- 1 7 11 62
- 40 70
- 43
78Add method observations
- Always add at a leaf node
- (Dont allow duplicates.)
- Algorithm is similar to search/contains.
79Recall recursive contains
- class MyBST
- private Node mRoot null
- public boolean containsRecursive ( int value )
- return containsRecursive( value, mRoot )
-
- public boolean containsRecursive ( int value,
Node n ) - //base case(s)
- if (nnull) return false //base case
- if (n.mDatavalue) return true //base case
- //recursive case(s)
- if (valuevalue, n.mLeft )
- return containsRecursive( value, n.mRight )
-
80Add method (in progress)
- class MyBST
- private Node mRoot null
- public void add ( int value )
- if (mRootnull) mRoot new Node( value )
- else add( value, mRoot )
-
- public void add ( int value, Node parent )
-
-
81Add method (in progress)
- class MyBST
- private Node mRoot null
- public void add ( int value )
- if (mRootnull) mRoot new Node( value )
- else add( value, mRoot )
-
- public void add ( int value, Node parent )
- //base case(s)
- assert parent!null //should never happen!
- if (valueparent.mData) return //disallow
duplicates -
-
82Completed add method
- class MyBST
- private Node mRoot null
- public void add ( int value )
- if (mRootnull) mRoot new Node( value )
- else add( value, mRoot )
-
- public void add ( int value, Node parent )
- //base case(s)
- assert parent!null //should never happen!
- if (valueparent.mData) return //disallow
duplicates - //possibly recursive case(s)
- if (value
- if (parent.mLeftnull) parent.mLeft new
Node( value ) - else add( value, parent.mLeft )
- else
- if (parent.mRightnull) parent.mRight
new Node( value ) - else add( value, parent.mRight )
83Node removal method
- Similar to contains and add but more difficult.
84Node removal leaf node example
Removal of leaf node is trivial. Now you see it .
. .
85Node removal leaf node example
Removal of leaf node is trivial. Now you see it .
. . now you dont!
86Node removal interior node example
Removal of interior node is tricky! We can even
remove the root! Remember only one of
11 or 62 needs to exist for 15 to be an interior
node.
87Node removal interior node example
Removal of interior node is tricky! We can even
remove the root! Remember only one of
11 or 62 needs to exist for 15 to be an interior
node.
88Node removal interior node example
Removal of interior node is tricky! We can even
remove the root! Remember only one of
11 or 62 needs to exist for 15 to be an interior
node.
89Node removal interior node example (alternative)
Removal of interior node is tricky! We can even
remove the root! Remember only one of
11 or 62 needs to exist for 15 to be an interior
node.
90Node removal interior node example (alternative)
Removal of interior node is tricky! We can even
remove the root! Remember only one of
11 or 62 needs to exist for 15 to be an interior
node.
91Node removal (but first, we will need an
additional function)
- //this function adds node value to subtree
parent assuming that - // value's data is greater than all data in
subtree parent - private void insertRight ( Node value, Node
parent ) - //precondition(s)
- assert value !null //should never happen!
- assert parent!null //should never happen!
- assert value.mDataparent.mData //should never
happen! - //base and possibly recursive cases
- if (parent.mRightnull)
- parent.mRight value //base
- else
- insertRight( value, parent.mRight )
//recursive
92Node removal
- public boolean remove ( int value )
- if (mRootnull) return false
- if (mRoot.mDatavalue) //remove root?
- //if possible, make left node new root and add
right to left - if (mRoot.mLeft!null)
- insertRight( mRoot.mRight, mRoot.mLeft )
- mRoot mRoot.mLeft
- else if (mRoot.mRight!null)
- mRoot mRoot.mRight
- else
- mRoot null
-
- return true
-
- //not removing the root
- if (valuemRoot, mRoot.mLeft )
- else return remove( value, mRoot, mRoot.mRight
)
93Node removal helper method
- private boolean remove ( int value, Node parent,
Node current ) - if (currentnull) return false
- if (current.mDatavalue)
- //if possible, make left node new root and add
right to left - if (current.mLeft!null)
- insertRight( current.mRight, current.mLeft )
- if (parent.mLeftcurrent) parent.mLeft
current.mLeft - else parent.mRight current.mLeft
- else if (current.mRight!null)
- if (parent.mLeftcurrent) parent.mLeft
current.mRight - else parent.mRight current.mRight
- else
- if (parent.mLeftcurrent) parent.mLeft
null - else parent.mRight null
-
- return true
-
- //keep trying to find the node to remove
- if (valuecurrent, current.mLeft )
94BST efficiency
- A BST is very efficient when balanced.
- Balancing is a topic for future classes.
- What does a BST degrade into when not balanced?
- Height of a balanced BST?
95Java and trees
- Of course, Java already contains an efficient BST
implementation called a TreeSet. - This implementation provides guaranteed log(n)
time cost for the basic operations (add, remove
and contains). - See http//java.sun.com/j2se/1.5.0/docs/api/java/u
til/TreeSet.html
96Games and trees (not BSTs)
- Enumerate possibilities
- Choose best alternative
97Games and trees (not BSTs)
- Note the arity is sometimes 3, 2, or 5.
- Difference between children and siblings.
98Games and trees (not BSTs)
- Note the arity is sometimes 3, 2, or 5.
- Difference between children and siblings.
class Node int mData Node mChild Node mSibl
ing