Download presentation
Presentation is loading. Please wait.
Published byAdrian Quinn Modified over 9 years ago
1
1 Chapter 10 Trees
2
2 Definition of Tree A tree is a set of linked nodes, such that there is one and only one path from a unique node (called the root node) to every other node in the tree. A path exists from node A to node B if one can follow a chain of pointers to travel from node A to node B.
3
3 A E F B C D G A set of linked nodes Paths There is one path from A to B There is a path from D to B There is also a second path from D to B.
4
4 A E F B C D G There is no path from C to any other node. Paths (cont.)
5
5 Cycles There is no cycle (circle of pointers) in a tree. Any linked structure that has a cycle would have more than one path from the root node to another node.
6
6 Example of a Cycle A C D B E C → D → B → E → C
7
7 Tree Cannot Have a Cycle A C D B E 2 paths exist from A to C: 1. A → C 2. A → C → D → B → E → C
8
8 Example of a Tree A C B D E F G root In a tree, every pair of linked nodes have a parent-child relationship (the parent is closer to the root)
9
9 Example of a Tree (cont.) A C B D E F G root For example, C is a parent of G
10
10 Example of a Tree (cont.) A C B D E F G root E and F are children of D
11
11 Example of a Tree (cont.) A C B D E F G root The root node is the only node that has no parent.
12
12 Example of a Tree (cont.) A C B D E F G root Leaf nodes (or leaves for short) have no children.
13
13 Subtrees A B C I K D E F J G H subtree root A subtree is a part of a tree that is a tree in itself
14
14 Binary Trees A binary tree is a tree in which each node can only have up to two children…
15
15 NOT a Binary Tree A B C I K D E F J G H root C has 3 child nodes.
16
16 Example of a Binary Tree A B C I K E J G H root The links in a tree are often called edges
17
17 Levels A B C I K E J G H root level 0 level 1 level 2 level 3 The level of a node is the number of edges in the path from the root node to this node
18
18 Full Binary Tree B D H root I A E J K C F L M G N O In a full binary tree, each node has two children except for the nodes on the last level, which are leaf nodes
19
19 Complete Binary Trees A complete binary tree is a binary tree that is either –a full binary tree –OR –a tree that would be a full binary tree but it is missing the rightmost nodes on the last level
20
20 NOT a Complete Binary Trees B D H root A E C F G I Missing non-rightmost nodes on the last level
21
21 Complete Binary Trees (cont.) B D H root I A E J K C F L G Missing rightmost nodes on the last level
22
22 Complete Binary Trees (cont.) B D H root I A E J K C F L M G N O A full binary tree is also a complete binary tree.
23
23 Binary Search Trees A binary search tree is a binary tree that allows us to search for values that can be anywhere in the tree. Usually, we search for a certain key value, and once we find the node that contains it, we retrieve the rest of the info at that node. Therefore, we assume that all values searched for in a binary search tree are distinct.
24
24 Properties of Binary Search Trees A binary search tree does not have to be a complete binary tree. For any particular node, –the key in its left child (if any) is less than its key. –the key in its right child (if any) is greater than or equal to its key. Left < Parent <= Right.
25
25 Binary Search Tree (BST) Node template BSTNode { T info; BSTNode *left; BSTNode *right; }; The implementation of a binary search tree usually just maintains a single pointer in the private section called root, to point to the root node.
26
26 Inserting Nodes Into a BST 37, 2, 45, 48, 41, 29, 20, 30, 49, 7 Objects that need to be inserted (only key values are shown): root: NULL BST starts off empty
27
27 Inserting Nodes Into a BST (cont.) 37, 2, 45, 48, 41, 29, 20, 30, 49, 7 root 37
28
28 Inserting Nodes Into a BST (cont.) 2, 45, 48, 41, 29, 20, 30, 49, 7 root 37 2 < 37, so insert 2 on the left side of 37
29
29 Inserting Nodes Into a BST (cont.) 2, 45, 48, 41, 29, 20, 30, 49, 7 root 37 2
30
30 Inserting Nodes Into a BST (cont.) 45, 48, 41, 29, 20, 30, 49, 7 root 37 2 45 > 37, so insert it at the right of 37
31
31 Inserting Nodes Into a BST (cont.) 45, 48, 41, 29, 20, 30, 49, 7 root 37 2 45
32
32 Inserting Nodes Into a BST (cont.) 48, 41, 29, 20, 30, 49, 7 root 37 2 45 When comparing, we always start at the root node 48 > 37, so look to the right
33
33 Inserting Nodes Into a BST (cont.) 48, 41, 29, 20, 30, 49, 7 root 37 2 45 This time, there is a node already to the right of the root node. We then compare 48 to this node 48 > 45, and 45 has no right child, so we insert 48 on the right of 45
34
34 Inserting Nodes Into a BST (cont.) 48, 41, 29, 20, 30, 49, 7 root 37 2 45 48
35
35 Inserting Nodes Into a BST (cont.) 41, 29, 20, 30, 49, 7 root 37 2 45 48 41 > 37, so look to the right 41 < 45, so look to the left – there is no left child, so insert
36
36 Inserting Nodes Into a BST (cont.) 41, 29, 20, 30, 49, 7 root 37 2 45 48 41
37
37 Inserting Nodes Into a BST (cont.) 29, 20, 30, 49, 7 root 37 2 45 48 41 29 < 37, left 29 > 2, right
38
38 Inserting Nodes Into a BST (cont.) 29, 20, 30, 49, 7 root 37 2 45 48 4129
39
39 Inserting Nodes Into a BST (cont.) 20, 30, 49, 7 root 37 2 45 48 4129 20 < 37, left 20 > 2, right 20 < 29, left
40
40 Inserting Nodes Into a BST (cont.) 20, 30, 49, 7 root 37 2 45 48 4129 20
41
41 Inserting Nodes Into a BST (cont.) 30, 49, 7 root 37 2 45 48 4129 20 30 < 37 30 > 2 30 > 29
42
42 Inserting Nodes Into a BST (cont.) 30, 49, 7 root 37 2 45 48 4129 2030
43
43 Inserting Nodes Into a BST (cont.) 49, 7 root 37 2 45 48 4129 2030 49 > 37 49 > 45 49 > 48
44
44 Inserting Nodes Into a BST (cont.) 49, 7 root 37 2 45 48 4129 203049
45
45 Inserting Nodes Into a BST (cont.) 7 root 37 2 45 48 4129 203049 7 < 37 7 > 2 7 < 29 7 < 20
46
46 Inserting Nodes Into a BST (cont.) 7 root 37 2 45 48 4129 203049 7
47
47 Inserting Nodes Into a BST (cont.) root 37 2 45 48 4129 203049 All elements have been inserted 7
48
48 Searching for a Key in a BST root 37 2 45 48 4129 203049 Searching for a key in a BST uses the same logic 7 Key to search for: 29
49
49 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 29 29 < 37 7
50
50 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 29 29 > 2 7
51
51 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 29 29 == 29 FOUND IT! 7
52
52 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 3 7
53
53 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 3 3 < 7 7 3 < 20 3 < 29 3 > 2 3 < 37
54
54 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 3 When the child pointer you want to follow is set to NULL, the key you are looking for is not in the BST 7
55
55 Searching a BST is Quicker than Array or Linked List root 37 2 45 48 4129 203049 Search for a key in this BST takes max 5 comparisons (key = 7) 7
56
56 Searching a BST is Quicker than Array or Linked List (cont.) 37, 2, 45, 48, 41, 29, 20, 30, 49, 7 Searching for a key in linear data structures, such as array or linked list, takes max 10 comparisons (key = 7). In fact searching for key 29, 20, 30, 49, and 7 all takes more than 5 comparisons. Overall slower than BST. The main advantage of BST over linear data structures is quicker search.
57
57 Deleting a BST Node Deleting a node in a BST is a little tricky – it has to be deleted so that the resulting structure is still a BST with each node greater than its left child and less than its right child. Deleting a node is handled differently depending on whether the node: –has no children –has one child –has two children
58
58 Deletion Case 1: No Children root 37 2 45 48 4129 203049 Node 49 has no children – to delete it, we just remove it
59
59 Deletion Case 1: No Children (cont.) root 37 2 45 48 4129 2030
60
60 Deletion Case 2: One Child root 37 2 45 48 4129 203049 Node 48 has one child – to delete it, we just splice it out
61
61 Deletion Case 2: One Child (cont.) root 37 2 45 48 4129 203049 Node 48 has one child – to delete it, we just splice it out
62
62 Deletion Case 2: One Child (cont.) root 37 2 45 4129 203049
63
63 Deletion Case 2: One Child (cont.) root 37 2 45 48 4129 203049 Another example: node 2 has one child – to delete it we also splice it out
64
64 Deletion Case 2: One Child (cont.) root 37 2 45 48 4129 203049 Another example: node 2 has one child – to delete it we also splice it out
65
65 Deletion Case 2: One Child (cont.) root 37 45 48 4129 203049
66
66 Deletion Case 3: Two Children root 37 2 45 48 4129 203049 Node 37 has two children…
67
67 Deletion Case 3: Two Children (cont.) root 37 2 45 48 4129 203049 to delete it, first we find the greatest node in its left subtree
68
68 Deletion Case 3: Two Children (cont.) root 37 2 45 48 4129 203049 First, we go to the left once, then follow the right pointers as far as we can
69
69 Deletion Case 3: Two Children (cont.) root 37 2 45 48 4129 203049 30 is the greatest node in the left subtree of node 37
70
70 Deletion Case 3: Two Children (cont.) root 37 2 45 48 4129 203049 Next, we copy the object at node 30 into node 37
71
71 Deletion Case 3: Two Children (cont.) root 30 2 45 48 4129 2049 Finally, we delete the lower red node using case 1 or case 2 deletion
72
72 Deletion Case 3: Two Children (cont.) root 30 2 45 48 4129 2049 Let’s delete node 30 now
73
73 Deletion Case 3: Two Children (cont.) root 30 2 45 48 4129 2049 29 is the greatest node in the left subtree of node 30
74
74 Deletion Case 3: Two Children (cont.) root 30 2 45 48 4129 2049 Copy the object at node 29 into node 30
75
75 Deletion Case 3: Two Children (cont.) root 29 2 45 48 4129 2049 This time, the lower red node has a child – to delete it we use case 2 deletion
76
76 Deletion Case 3: Two Children (cont.) root 29 2 45 48 4129 2049 This time, the lower red node has a child – to delete it we use case 2 deletion
77
77 Deletion Case 3: Two Children (cont.) root 29 2 45 48 41 2049
78
78 Searching a BST is Quicker than Array or Linked List root 37 2 45 48 4129 203049 Search for a key in this BST takes max 5 comparisons (key = 7) 7
79
: 37 2 29 20 7 30 45 41 48 49 Traversing a BST There are 3 ways to traversal a BST (visit every node in BST): –1. Preorder (parent → left → right) –2. Inorder (left → parent → right) –3. Postorder (left → right → parent) Result of traversing BST (at pp. 55): –Preorder: –Inorder: –Postorder: 2 7 20 29 30 37 41 45 48 49 7 20 30 29 2 41 49 48 45 37
80
80 1 template 2 class BinarySearchTree { 3 BSTNode *root; 4 void preOrderInternal (BST *parent) { … } 5 void inOrderInternal (BST *parent) { … } 6 void postOrderInternal (BST *parent) { … } 7 void insertInternal (BST *parent, 8 T& newElement) { … } 9 bool searchInternal (BST *parent, T& target, 10 T& foundElement) { … } Binary Search Tree Class Template
81
81 11 public: 12 BinarySearchTree() { … } 13 ~BinarySearchTree() { … } 14 bool isEmpty() { … } 15 void preOrderTraversal() { … } 16 void inOrderTraversal() { … } 17 void postOrderTraversal() { … } 18 void insert (T element) { … } 19 bool search (T element, T& foundElement) { … } 20 void makeEmpty() { … } 21 } Binary Search Tree Class Template (cont.)
82
82 1 BinarySearchTree() 2 : root(NULL) { } 3 4 ~BinarySearchTree() 5 { 6 makeEmpty(); 7 } 8 9 bool isEmpty() 10 { 11 return root == NULL: 12 } Constructor, Destructor, IsEmpty()
83
83 2 void inOrderTraversal() 3 { 4inOrderInternal (root); 5 } The client uses the driver called InOrderTraversal. Printing Elements In Order The recursive function inOrderInternal is called. inOrderInternal prints all element in BST in sorted order, starting from root node.
84
84 2 void inOrderInternal (BSTNode *parent) 3 { 4 if (parent != NULL) { 5 inOrderInternal (parent->left); 6 cout info << " "; 7 inOrderInternal (parent->right); 8 } 9 } The base case occurs when parent is NULL – just returns. Printing Elements In Order (cont.)
85
85 2 void inOrderInternal (BSTNode *parent) 3 { 4 if (parent != NULL) { 5 inOrderInternal (parent->left); 6 cout info << " "; 7 inOrderInternal (parent->right); 8 } 9 } There are 2 recursive calls under the if – the first advances the pointer to the left child… and the second advances the pointer to the right child. Printing Elements In Order (cont.)
86
86 2 void inOrderInternal (BSTNode *parent) 3 { 4 if (parent != NULL) { 5 inOrderInternal (parent->left); 6 cout info << " "; 7 inOrderInternal (parent->right); 8 } 9 } Each recursive call approaches the base case… it goes down one level through the tree, and it get closer to the case where parent->left or parent->right is NULL. Printing Elements In Order (cont.)
87
87 2 void inOrderInternal (BSTNode *parent) 3 { 4 if (parent != NULL) { 5 inOrderInternal (parent->left); 6 cout info << " "; 7 inOrderInternal (parent->right); 8 } 9 } If the BST contains only one node, the root node is the only node – the left and right pointers of the root node will be set to NULL. Printing Elements In Order (cont.)
88
88 2 void inOrderInternal (BSTNode *parent) 3 { 4 if (parent != NULL) { 5 inOrderInternal (parent->left); 6 cout info << " "; 7 inOrderInternal (parent->right); 8 } 9 } parent->left is NULL, so NULL is passed into parent of the new inOrderInternal function. Printing Elements In Order (cont.)
89
89 2 void inOrderInternal (BSTNode *parent) 3 { 4 if (parent != NULL) { 5 inOrderInternal (parent->left); 6 cout info << " "; 7 inOrderInternal (parent->right); 8 } 9 } Since parent is NULL in the new inOrderInternal function, it will return right away. Printing Elements In Order (cont.)
90
90 2 void inOrderInternal (BSTNode *parent) 3 { 4 if (parent != NULL) { 5 inOrderInternal (parent->left); 6 cout info << " "; 7 inOrderInternal (parent->right); 8 } 9 } parent->right is NULL – thus, the recursive function call immediately returns as before. Printing Elements In Order (cont.)
91
91 2 void inOrderInternal (BSTNode *parent) 3 { 4 if (parent != NULL) { 5 inOrderInternal (parent->left); 6 cout info << " "; 7 inOrderInternal (parent->right); 8 } 9 } Printing Elements In Order (cont.) In fact inOrderInternal works correctly when there is only 0, 1 or many node in the BST.
92
92 2 void inOrderInternal (BSTNode *parent) 3 { 4 if (parent != NULL) { 5 inOrderInternal (parent->left); 6 cout info << " "; 7 inOrderInternal (parent->right); 8 } 9 } Printing Elements In Order (cont.) inOrderInternal is called once from the driver inOrderTraversal. Then, for each node in the tree, 2 calls to inOrderInternal are made, giving us a total of 2n + 1 calls where n is the number of nodes.
93
93 2 void preOrderInternal (BSTNode *parent) 3 { 4 if (parent != NULL) { 5 cout info << " "; 6 preOrderInternal (parent->left); 7 preOrderInternal (parent->right); 8 } 9 } Printing Elements Pre Order preOrderInternal prints the parent first.
94
94 2 void postOrderInternal (BSTNode *parent) 3 { 4 if (parent != NULL) { 5 postOrderInternal (parent->left); 6 postOrderInternal (parent->right); 7 cout info << " "; 8 } 9 } Printing Elements Post Order postOrderInternal prints the parent last.
95
95 1 bool search (T target, T& foundElement) { 2 return searchInternal (root, target, foundElement); 3 } 4 5 void insert ( T& newElement) { 6 insertInternal (root, newElement); 7 } Searching and Insertion in BST
96
96 Searching and Insertion in BST We can actually figure out searchInternal and insertInternal using the same recursive logic as traversal in BST.
97
References Childs, J. S. (2008). Trees. C++ Classes and Data Structures. Prentice Hall. 97
Similar presentations
© 2024 SlidePlayer.com Inc.
All rights reserved.