Title: CS 1371 Introduction to Computing for Engineers
1CS 1371Introduction to Computing for Engineers
2Other Data Structures Trees
Learning Objectives Understanding Trees
- Nature of Trees
- Binary Trees Traversal
- Binary Search Trees
- Inserting
- Deleting
3Background
- There is a spectrum of complexity for Dynamic
Data Structures
- Lists
- At most, one child
- No cycles
- Binary Trees
- At most, two children
- No cycles
- N-ary Trees
- Any number of children
- Graphs
- Any number of children
- Cycles permitted
4Trees
- Hierarchical data structure
- Nodes with 0 to many children
- One special node designated root
- Acyclic
- Recursive definition
5Binary Trees
- Hierarchical data structure
- Nodes with 0 to 2 children
- One special node designated root
- Acyclic
- Recursive definition
6Recursive Definition?
- A binary tree is either
- A null reference
- A node with two children each of which is a
binary tree - This recursive definition is why many tree
algorithms are very simple when stated recursively
7List was Our Main Dynamic Data Structure
Weve been dealing with the fairly simple
self-referential data definition of a list.
- A ListOfStuff is either
- the empty list null or
- A LLNode containing data and next where data is
an Object and next is a ListOfStuff
8OK, got that
Weve modeled sets of data where it is only
necessary to have one reference to the next
location in the set of data. For example, a list
of grocery items found on most college freshmens
shopping lists
null
9null
Sugar-laden food of choice
Non-alcoholic beverages
No-Doz
We know the current grocery item, and we have a
link to the next grocery item (if were not at
the end of our list)
10More Complicated Situations?
Say you want to model data that inherently has
more than one relationship between items? Like
a Family Tree
11The Family Tree
There are many different ways to represent a
family tree. The style we will show is an
ancestor family tree. From a given person in the
family tree, we will be able to easily access
information about the persons ancestors, but not
their descendants. Which means.
12In this particular family tree, we add a new
node to the tree every time a child is born.
We record certain information about the child
(name, date of birth (dob), date of death (dod))
as well as who the parents are (mother, father).
13But if we stop to think about it, arent the
father and mother both children themselves?
So wouldnt they too have properties like name,
dob, dod and father and mother?
So we need a data definition that contains two
references one to the father and one to the
mother
14Lets Develop a Data Definition
// A child is a TreeNode containing //
name, dob, dod, father, mother // where father
and mother are child structures // name is a
symbol and // dob and dod are numbers
Looks good, right?
15That Almost Works but
That data definition seems to workbut there are
problems. Lets say you have quite an extensive
family history going all the way back to your
great-great-great-great-great grandfather
Billy-Bob Jones born in the year 1810 to Well,
the records of that portion of your family tree
were destroyed in a tragic fire You dont
actually know who your great6 grandfather or
grandmother actually is
16So We have to Reflect that Fact
Your father and mother values could be
non-existent. They could be null. So we change
our data definition a little
- A FamilyNode is either
- null or
- A TreeNode containing
- name, dob, dod, father, mother
- where father mother are FamilyNodes , name is a
symbol, and dob and dod are numbers
17So What have We Made?
A data structure that references itself twice If
we wanted to think about it visually
18Lets Start with Information About You
Gustav
1981
-1
Father left
Mother right
null
null
19We Add More About Our Family
null
null
null
null
20And more
null
null
null
null
null
null
null
null
null
null
null
null
21What About code?
Is this much more complex than what weve done
before? Lets see what a typical function would
look like for a family tree Well derive a
processFamilyNode
22Observations
- We made some choices
- to indicate unknown parents
- we choose null
- to indicate that the person is still alive (no
date of death) - we choose dod -1
- can create an new node for each person
- Hint helps to draw a picture first
answer
left answer
right answer
23Self-referencing Structure ExampleFamily Tree
null
null
null
null
null
null
Carl, 1926, 1978
Bettina, 1928, 1986
Fred, 1949, alive
Eva, 1951, alive
Dave, 1948, 1997
Adam, 1946, alive
24Questions?
25Looking Again at the Ancestral Tree
It is an example of a new Dynamic Data Type
called a Tree.
26Trees in Generalthe Terminology
A tree consists of nodes. Each node contains data
as well as references/links/pointers to one or
more other nodes. Any such reference might be
null. The first or top node in a tree is
called the root node. A parent node points
(references/links) to child nodes. Any node that
has two null children references is called a leaf
node.
27Root
Leaf
Leaf
null
null
null
null
null
28Parent
Child
null
null
null
null
null
29The Tree Class
- The Binary Tree class will have some similarities
to a Linked List class - Need a BTNode which contains three items
- data, an Object
- left and right, references to other BTNodes or
null - In either event we will need
- Appropriate methods (equals, compareTo,
toString() - And, of course, a test script
30A Tree Class
- A reference to a BTNode that is the root node
- A constructor
- insert
- contains
- count
- height
- delete
Let's code!
31One more level of Abstraction
- We need to separate the information about the
people from the maintenance of the data structure
Collecting the data
Person
BinaryTree
get/setName
get/setRoot
gt
Has-a
Has-a
get/setDob
count
BTNode
eq
get/setData
get/setDod
largest
get/setLeft
find
get/setRight
Operations on the Content
Has-a
Has-a
Operations on the tree
BTNode
BTNode
32Consequences
- We can use the same tree structure to contain
different data - We can specialize the tree by deriving more
specific classes
BinaryTree
count
largest
Has-a
Is-a
smallest
find
uses
AncestorTree
ancestors
oldest
33Manipulating Trees Recursively
function ans processTreeNode(here)
processTreeNode(getLeft(here))
processTreeNode(getRight(here))
processData(getData(here))
Combine the results to achieve what you are
seeking
Use a recursive call for each self-reference
34Manipulating Structures
Example counting a tree
- function ans count(here)
- if isempty(here)
- ans 0
- else
- ans count(getLeft(here))
- count(getRight(here))
- 1
- end
Matlabs test for null
here reminds us that we are moving recursively
through the tree
35Code Used BTNode
- function btn BTNode( d, l, r )
- BTNode constructor
- if nargin 0
- btn.data
- btn.left
- btn.right
- btn class(btn,'BTNode')
- else
- if isa(d, 'BTNode')
- btn d
- else
- btn.data d
- switch nargin
- case 1
- btn.left
- btn.right
- case 2
- btn.left l
- btn.right
36Code Used Binary Tree
- function bt BinaryTree( r )
- BTNode constructor
- if nargin 0
- bt.root
- bt class(bt,'BinaryTree')
- else
- if isa(r, 'BinaryTree')
- bt r
- else
- bt.root r
- bt class(bt,'BinaryTree')
- end
- end
37Code Used Number Tree
- ll BTNode(floor(100rand), BTNode(floor(100rand
)), BTNode(floor(100rand))) - lr BTNode(floor(100rand), BTNode(floor(100rand
)), BTNode(floor(100rand))) - rl BTNode(floor(100rand), BTNode(floor(100rand
)), BTNode(floor(100rand))) - rr BTNode(floor(100rand), BTNode(floor(100rand
)), BTNode(floor(100rand))) - l BTNode(floor(100rand), ll, lr)
- r BTNode(floor(100rand), rl, rr)
- numbers BinaryTree( BTNode(floor(100rand), l,
r) ) - fprintf('largest number is f\n',
largest(numbers) ) - fprintf('pre-order list is s\n',
preOrderString(numbers) ) - fprintf('in-order list is s\n',
inOrderString(numbers) ) - fprintf('breadth-first list s\n',
BFTString(numbers)) - n 1
- while n gt 0
- n input('number to find breadth first ')
- if n gt 0
- fprintf('breadth-first find d\n',
BFFind(numbers, n)) - end
- end
38Code Used In-Order Traversal
- function str inOrderString(bt)
- _at_BinaryTree\inOrderString
- str inOrderString(bt)
- str RinOrderString(bt.root)
- function str RinOrderString(here)
- recursive in-order processing
- if isempty(here)
- str ''
- else
- str RinOrderString(getLeft(here)) ' ' ...
- char(here) ' ' ...
- RinOrderString(getRight(here))
- end
39Code Used Breadth-First Find
- function ans BFFind(bt, what)
- _at_BinaryTree\BFFind
- q Queue
- enqueue(q, bt.root )
- found false
- ans
- while found isEmpty(q)
- node dequeue(q)
- check the data we just dequeued
- found (node what)
- if found
- enqueue the children of this node
- left getLeft(node)
- if isempty(left)
- enqueue(q, left )
- end
- right getRight(node)
- if isempty(right)
- enqueue(q, right )
40Testing
- carl BTNode( Person('Carl', 1926, 1978), ,
) - bettina BTNode(Person('Bettina', 1928, 1976))
- adam BTNode(Person('Adam', 1946, -1), carl,
bettina) - dave BTNode(Person('Dave', 1948, 1997), carl,
bettina) - eva BTNode(Person('Eva', 1951, -1), carl,
bettina) - fred BTNode(Person('Fred', 1949, -1))
- gustav BTNode(Person('Gustav', 1985, -1), fred,
eva ) - family BinaryTree(gustav)
- fprintf('Gustav has d ancestors!\n',
count(family) ) - fprintf('oldest member is s\n', char(
largest(family) ) ) - fprintf('in-order list s\n', inOrderString(famil
y)) - --------------------------------------------------
------------ - Carl
- Bettina
- Adam
- Dave
- Eva
- Fred
41A New Type of Tree a Binary Search Tree
Probably the most famous type of tree in
Computer Science is related to the Binary
Tree. A binary tree is a tree structure in which
each node has AT MOST two child nodes linked
directly off the parent node. The ancestral tree
was a binary tree.
42null
null
null
null
By itself, a binary tree has no inherent order.
There is no ordered relationship between the data
in the parent node and the data in the child
nodes.
43Binary Search Trees
- Binary Tree
- Left subtree contains key values less than node
- Right subtree contains key value greater than
node - No duplicates
50
40
95
42
30
63
99
37
10
Normally handled specially
44Searching a BST
- function ans find(bst, n)
- BST\find
- ans rFind( getRoot(bst), n)
- function ans rFind(here, n)
-
- if isempty(here)
- ans
- elseif getData(here) n
- ans getData(here)
- elseif getData(here) gt n
- ans rFind(getLeft(here), n)
- else
- ans rFind(getRight(here), n)
- end
50
40
95
42
30
63
99
37
10
45Binary Search Trees
- Performance
- Search O(log N)
- Insert O(log N)
- Traverse O(N)
- Performance O()'s assume tree is relatively
balanced
50
50
40
40
95
30
42
30
63
99
10
37
10
46Inserting into a BST
- We have a Binary Search Tree
- It can be empty,
- Or have some elements in it already
- We want to add an element to it
- Inserting/adding involves 2 steps
- Find the correct location
- Do the steps to add a new node
- Must maintain "search" structure
47Finding the Correct Location
Start with this tree
12
41
3
98
7
48Finding the Correct Location
Where would 4 be added?
12
41
3
98
7
49Finding the Correct Location
4
To the topdoesnt work
12
41
3
98
7
50Finding the Correct Location
12
41
4
98
3
In the middledoesnt work
7
51Finding the Correct Location
12
41
3
98
7
At the bottomDOES work!
4
52Finding the Correct Location
- Must maintain "search" structure
- Everything to left is less than current,
- Everything to right is greater than current
- Adding at the "bottom" guarantees we keep search
structure. - Well go recursively to get to the "bottom"
- when current.right null
- or current.left null
53Inserting into a BST
- function insert(bst, n)
- _at_BST\insert
- setRoot(bst, rInsert(getRoot(bst), n) )
- assignin('caller', inputname(1), bst)
- function node rInsert(here, n)
- recursive insertion into a BST
- if isempty(here)
- node BTNode(n)
- elseif getData(here) n
- node here Policy decision on
equality - throw an error?
- elseif getData(here) gt n
- node BTNode(getData(here), ...
- rInsert(getLeft(here), n), ...
- getRight(here))
- else
- node BTNode(getData(here), ...
54Questions?
55Deleting from a BST
56The Scenario
- We have a Binary Search Tree and want to remove
some element based upon a match. - Must preserve "search" property
- Must not lose any elements (i.e. only remove the
one targeted element)
57BST Deletion
- Search for desired item.
- If not found, then return NULL or print error.
- If found, perform steps necessary to accomplish
removal from the tree.
58Four Scenarios of Deletion
- Delete a leaf node
- Delete a node with only one child (left)
- Delete a node with only one child (right)
- Delete a node with two children
- Cases 2 and 3 are comparable and only need slight
changes in the conditional statement used
59Delete a Leaf Node
- Simply make the parent node null. This will
remove the node from the tree.
60Delete a Leaf Node
- Simply make the parent node null. This will
remove the node from the tree. - Lets delete the 42.
61Delete a Leaf Node
- Simply make the parent node null. This will
remove the node from the tree.
62Delete a Leaf Node
- Simply make the parent node null. This will
remove the node from the tree. - Ta-Da
63Questions?
64Delete a Node with One Child
- Determine if it has a left or a right child.
- Move the child reference to the parent reference
65Delete a Node with One Child
- Determine if it has a left or a right child.
- Move the child reference to the parent reference
- Lets delete the 14
66Delete a Node with One Child
- Determine if it has a left or a right child.
- Move the child reference to the parent reference
67Delete a Node with One Child
- Determine if it has a left or a right child.
- Ta-Da
68Delete a Node with One Child
- Determine if it has a left or a right child.
- Move the child reference to the parent reference
- Now, delete the 71
69Delete a Node with One Child
- Determine if it has a left or a right child.
- Move the child reference to the parent reference
70Delete a Node with One Child
- Determine if it has a left or a right child.
- There!
71Questions?
72Delete a Node with Two Children
- Copy a replacement value from a descendent node.
- Largest from left
- Smallest from right
- Then delete that descendent node to remove the
duplicate value. - We know this will be an easier case.
73Delete a Node with Two Children
74Delete a Node with Two Children
- Look to the left sub-tree
75Delete a Node with Two Children
- Find and copy the largest value (this will erase
the old value but creates a duplicate).
76Delete a Node with Two Children
- The resulting tree so far
77Delete a Node with Two Children
- Now, delete the duplicate from the left sub-tree.
78Delete a Node with Two Children
- The final resulting tree still has the proper
search structure.
79Delete a Node with Two Children
80Delete a Node with Two Children
- Look to the right sub-tree.
81Delete a Node with Two Children
- Find and copy the smallest value (this will erase
the old value but creates a duplicate).
82Delete a Node with Two Children
- The resulting tree so far.
83Delete a Node with Two Children
- Now, delete the duplicate from the left sub-tree.
84Delete a Node with Two Children
- The final resulting tree still has search
structure.
85Delete a Node with Two Children
- But what if that node had a right child with lots
of nodes ???
86Delete a Node with Two Children
- No problem its still just a deletion of a node
with 1 child (as described previously)
All these nodes must be gt 108 but lt 116
87Delete a Node with Two Children
- Final tree with everything in correct BST order.
88Deleting from a BST 1
- function delete(bst, n)
- _at_BST\delete
- setRoot(bst, rDelete(getRoot(bst), n) )
- assignin('caller', inputname(1), bst)
- function node rDelete(here, n)
-
- if isempty(here)
- node
- elseif getData(here) n
- node deleteThis(here)
- elseif getData(here) gt n
- node BTNode(getData(here), ...
- rDelete(getLeft(here), n), ...
- getRight(here))
- else
- node BTNode(getData(here), ...
- getLeft(here), ...
89Deleting from a BST 2
- function node deleteThis(here)
-
- left getLeft(here)
- right getRight(here)
- if isempty(left)
- node right
- elseif isempty(right)
- node left
- else
- value rest deleteLargest(left)
- node BTNode(value, rest, right)
- end
- function value node deleteLargest(here)
-
- right getRight(here)
- if isempty(right)
- value getData(here)
90Test Script
- nn input('How many nodes? ')
- bst BST( BTNode(50) )
- for in 1nn
- insert(bst, ceil(100rand))
- end
- fprintf('number is d (started with d)\n',
count(bst), nn1 ) - fprintf('largest number is d\n', largest(bst) )
- fprintf('pre-order list is s\n',
preOrderString(bst) ) - fprintf('in-order list is s\n',
inOrderString(bst) ) - fprintf('breadth-first list s\n',
BFTString(bst)) - n 1
- while n gt 0
- n input('number to find ')
- if n gt 0
- ans find(bst, n)
- BSTdelete(bst, n)
- fprintf('number is d (started with
d)\n', count(bst), nn1 ) - fprintf('in-order list is s\n',
inOrderString(bst) ) - fprintf(' bst with d removed s\n', n,
BFTString(bst))
91Delete Overview
- Deleting a node from a binary search tree
involves two steps - Search for the element
- Then perform the deletion
- We must preserve the search structure and only
delete the element which matches. - Four scenarios
- Deleting a leaf node
- Deleting a node with only the left child
- Deleting a node with only the right child
- Deleting a node with both children
92Questions?
93(No Transcript)