Title: Binary Trees
1Chapter 20
220.1 Definition and Applications of Binary Trees
- A binary tree is a non-linear linked list where
each node may point to two other nodes.
3Definition and Applications of Binary Trees
- It is anchored at the top by a tree pointer,
which is like the head pointer in a linked list. - The first node in the list is called the root
node. - The root node has pointers to two other nodes,
which are called children, or child nodes.
4Definition and Applications of Binary Trees
- A node that has no children is called a leaf
node. - All pointers that do not point to a node are set
to NULL.
5Definition and Applications of Binary Trees
- Binary trees can be divided into subtrees. A
subtree is an entire branch of the tree, from one
particular node down.
6Definition and Applications of Binary Trees
- Binary trees are excellent data structures for
searching large amounts of information. They are
commonly used in database applications to
organize key values that index database records. - When used to facilitate searches, a binary tree
is called a binary search tree.
7Definition and Applications of Binary Trees
- Information is stored in binary search trees in a
way that makes a binary search simple. For
example, look at Figure 20-3.
Values are stored in a binary tree so that a
node's left child holds data whose value is less
than the node's data, and the node's right child
holds data whose value is greater tan the node's
data.
8Definition and Applications of Binary Trees
- It is also true that all the nodes to the left of
a node hold values less than the node's value.
Likewise, all the nodes to the right of a node
hold values that are greater than the node's
data. - When an application is searching a binary tree,
it starts at the root node. If the root node does
not hold the search value, the application
branches either to the left or right child,
depending on whether the search value is less
than or grater than the value at the root node.
9Definition and Applications of Binary Trees
- This process continues until the value is found.
Figure 20-4 illustrates the search pattern for
finding the value P in the binary tree.
1020.2 Binary Search Tree Operations
- Creating a Node We will demonstrate binary tree
operations using the IntBinaryTree class. - The basis of our binary tree node is the
following struct declaration
struct TreeNode int value TreeNode
left TreeNode right
- The struct is implemented in the class shown
next
11IntBinaryTree.h
class IntBinaryTreepublic struct
TreeNode int value TreeNode
left TreeNode right TreeNode
root void destroySubTree(TreeNode ) void
deleteNode(int, TreeNode ) void
makeDeletion(TreeNode ) void
displayInOrder(TreeNode ) void
displayPreOrder(TreeNode ) void
displayPostOrder(TreeNode )
12IntBinaryTree.h (continued)
public IntBinaryTree() // Constructor root
NULL IntBinaryTree() // Destructor
destroySubTree(root) void insertNode(int) bo
ol searchNode(int) void remove(int) void
showNodesInOrder(void) displayInOrder(root)
void showNodesPreOrder() displayPreOrder(ro
ot) void showNodesPostOrder() displayPostO
rder(root)
1320.2 Binary Search Tree Operations
- Inserting a NodeFirst, a new node is allocated
and its value member is initialized with the new
value. - The left and right child pointers are set to
NULL, because all nodes must be inserted as leaf
nodes. - Next, we determine if the tree is empty. If so,
we simply make root point to it, and there is
nothing else to be done. But, if there are nodes
in the tree, we must find the new node's proper
insertion point.
1420.2 Binary Search Tree Operations
- If the new value is less than the root node's
value, we know it will be inserted somewhere in
the left subtree. Otherwise, the value will be
inserted into the right subtree. - We simply traverse the subtree, comparing each
node along the way with the new node's value, and
deciding if we should continue to the left or the
right. - When we reach a child pointer that is set to
NULL, we have found out insertion point.
15The insertNode Member Function
void IntBinaryTreeinsertNode(int
num) TreeNode newNode, // Pointer to a new
node nodePtr // Pointer to traverse
the tree // Create a new node newNode new
TreeNode newNode-gtvalue num newNode-gtleft
newNode-gtright NULL if (!root) // Is the
tree empty? root newNode else nodePtr
root
16The insertNode Member Function
while (nodePtr ! NULL) if (num lt
nodePtr-gtvalue) if (nodePtr-gtleft) n
odePtr nodePtr-gtleft else nodePt
r-gtleft newNode break
17The insertNode Member Function
else if (num gt nodePtr-gtvalue) if
(nodePtr-gtright) nodePtr
nodePtr-gtright else nodePtr-gtright
newNode break else
cout ltlt "Duplicate value found in
tree.\n" break
18Program 20-1
// This program builds a binary tree with 5
nodes.include ltiostream.hgtinclude
"IntBinaryTree.hvoid main(void) IntBinaryTre
e tree cout ltlt "Inserting nodes.
" tree.insertNode(5) tree.insertNode(8) tree
.insertNode(3) tree.insertNode(12) tree.insert
Node(9) cout ltlt "Done.\n"
19Program 20-1
Figure 20-5 shows the structure of the binary
tree built by the program.
Note The shape of the tree is determined by the
order in which the values are inserted. The root
node in the diagram above holds the value 5
because that was the first value inserted.
20Traversing the Tree
- There are three common methods for traversing a
binary tree and processing the value of each
node - inorder
- preorder
- postorder
- Each of these methods is best implemented as a
recursive function.
21Inorder Traversal
- The nodes left subtree is traversed.
- The nodes data is processed.
- The nodes right subtree is traversed.
22Preorder Traversal
- The nodes data is processed.
- The nodes left subtree is traversed.
- The nodes right subtree is traversed.
23Postorder Traversal
- The nodes left subtree is traversed.
- The nodes right subtree is traversed.
- The nodes data is processed.
24The displayInOrder Member Function
void IntBinaryTreedisplayInOrder(TreeNode
nodePtr) if (nodePtr) displayInOrder(node
Ptr-gtleft) cout ltlt nodePtr-gtvalue ltlt
endl displayInOrder(nodePtr-gtright)
25The displayPreOrder Member Function
void IntBinaryTreedisplayPreOrder(TreeNode
nodePtr) if (nodePtr) cout ltlt
nodePtr-gtvalue ltlt endl displayPreOrder(nodePtr-
gtleft) displayPreOrder(nodePtr-gtright)
26The displayPostOrder Member Function
void IntBinaryTreedisplayPostOrder(TreeNode
nodePtr) if (nodePtr) displayPostOrder(no
dePtr-gtleft) displayPostOrder(nodePtr-gtright)
cout ltlt nodePtr-gtvalue ltlt endl
27Program 20-2
// This program builds a binary tree with 5
nodes.// The nodes are displayed with inorder,
preorder,// and postorder algorithms.include
ltiostream.hgtinclude "IntBinaryTree.hvoid
main(void) IntBinaryTree tree cout ltlt
"Inserting nodes.\n" tree.insertNode(5) tree.i
nsertNode(8) tree.insertNode(3) tree.insertNod
e(12) tree.insertNode(9)
28Program 20-2 (continued)
cout ltlt "Inorder traversal\n" tree.showNodesIn
Order() cout ltlt "\nPreorder traversal\n" tree
.showNodesPreOrder() cout ltlt "\nPostorder
traversal\n" tree.showNodesPostOrder()
29Program 20-2 (continued)
Program Output Inserting nodes.Inorder
traversal358912 Preorder
traversal538129
30Program 20-2 (continued)
Postorder traversal3 91285
31Searching the Tree
The IntBinaryTree class has a public member
function, SearchNode, which returns true if a
value is found in the tree, or false otherwise.
bool IntBinaryTreesearchNode(int
num) TreeNode nodePtr root while
(nodePtr) if (nodePtr-gtvalue
num) return true else if (num lt
nodePtr-gtvalue) nodePtr nodePtr-gtleft else
nodePtr nodePtr-gtright return false
32Program 20-3
// This program builds a binary tree with 5
nodes.// The SearchNode function determines if
the// value 3 is in the tree.include
ltiostream.hgtinclude "IntBinaryTree.hvoid
main(void) IntBinaryTree tree cout ltlt
"Inserting nodes.\n" tree.insertNode(5) tree.i
nsertNode(8) tree.insertNode(3) tree.insertNod
e(12) tree.insertNode(9)
33Program 20-3 (continued)
if (tree.searchNode(3)) cout ltlt "3 is found in
the tree.\n" else cout ltlt "3 was not found in
the tree.\n" Program Output Inserting
nodes.3 is found in the tree.
34Deleting a Node
- We simply find its parent and set the child
pointer that links to it to NULL, and then free
the node's memory. - But what if we want to delete a node that has
child nodes? We must delete the node while at the
same time preserving the subtrees that the node
links to.
35Deleting a Node
- There are two possible situations when we are
deleting a non-leaf node - A) the node has one child, or
- B) the node has two children.
36Deleting a Node
Figure 20-6 illustrates a tree in which we are
about to delete a node with one subtree.
37Deleting a Node
Figure 20-7 shows how we will link the node's
subtree with its parent.
38Deleting a Node
The problem is not as easily solved, however,
when the node we are about to delete has two
subtrees. For example, look at Figure 20-8.
39Deleting a Node
- We cannot attach both of the node's subtrees to
its parent, so there must be an alternative
solution. - One way is to attach the node's right subtree to
the parent, and then find a position in the right
subtree to attach the left subtree. The result is
shown in Figure 20-9.
40Deleting a Node
Figure 20-9.
41Deleting a Node
To delete a node from the IntBinaryTree, call the
public member function remove. The argument is
the value of the node that is to be deleted.
void IntBinaryTreeremove(int
num) deleteNode(num, root) The remove
member function calls the deleteNode member
function. It passes the value of the node to
delete, and the root pointer.
42The deleteNode Member Function
void IntBinaryTreedeleteNode(int num, TreeNode
nodePtr) if (num lt nodePtr-gtvalue) deleteNo
de(num, nodePtr-gtleft) else if (num gt
nodePtr-gtvalue) deleteNode(num,
nodePtr-gtright) else makeDeletion(nodePtr)
Notice the declaration of the nodePtr
parameter TreeNode nodePtr nodePtr is not
simply a pointer to a TreeNode structure, but a
reference to a pointer to a TreeNode structure.
Any action performed on nodePtr is actually
performed on the argument passed into nodePtr.
43The deleteNode Member Function
- else makeDeletion(nodePtr)
- The trailing else statement calls the
makeDeletion function, passing nodePtr as its
argument. - The makeDeletion function actually deletes the
node from the tree, and must reattach the deleted
nodes subtrees. - Therefore, it must have access to the actual
pointer in the binary tree to the node that is
being deleted. - This is why the nodePtr parameter in the
deleteNode function is a reference.
44The makeDeletion Member Function
void IntBinaryTreemakeDeletion(TreeNode
nodePtr) TreeNode tempNodePtr // Temporary
pointer, used in //
reattaching the left subtree. if (nodePtr
NULL) cout ltlt "Cannot delete empty
node.\n" else if (nodePtr-gtright
NULL) tempNodePtr nodePtr nodePtr
nodePtr-gtleft // Reattach the left
child delete tempNodePtr else if
(nodePtr-gtleft NULL) tempNodePtr
nodePtr nodePtr nodePtr-gtright // Reattach
the right child delete tempNodePtr
45The makeDeletion Member Function (continued)
// If the node has two children. else //
Move one node the right. tempNodePtr
nodePtr-gtright // Go to the end left
node. while (tempNodePtr-gtleft) tempNodePtr
tempNodePtr-gtleft // Reattach the left
subtree. tempNodePtr-gtleft nodePtr-gtleft te
mpNodePtr nodePtr // Reattach the right
subtree. nodePtr nodePtr-gtright delete
tempNodePtr
46Program 20-4
// This program builds a binary tree with 5
nodes.// The DeleteNode function is used to
remove two// of them.include
ltiostream.hgtinclude "IntBinaryTree.hvoid
main(void) IntBinaryTree tree cout ltlt
"Inserting nodes.\n" tree.insertNode(5) tree.i
nsertNode(8) tree.insertNode(3) tree.insertNod
e(12) tree.insertNode(9) cout ltlt "Here are
the values in the tree\n" tree.showNodesInOrder
()
47Program 20-4 (continued)
cout ltlt "Deleting 8...\n" tree.remove(8) cou
t ltlt "Deleting 12...\n" tree.remove(12) cout
ltlt "Now, here are the nodes\n" tree.showNodesIn
Order()
48Program 20-4 (continued)
Program Output Inserting nodes.Here are the
values in the tree358912Deleting
8...Deleting 12...Now, here are the nodes359
49Template Considerations for Binary Trees
- When designing your template, remember that any
data types stored in the binary tree must support
the lt, gt, and operators. - If you use the tree to store class objects, these
operators must be overridden.