Download presentation
Presentation is loading. Please wait.
Published byAnnice Small Modified over 9 years ago
1
1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 15 Other Data Structures Jeffrey S. Childs Clarion University of PA © 2008, Prentice Hall
2
2 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
3
3 Properties of Binary Search Trees A binary search tree does not have to be a complete binary tree (like a heap) 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 its key
4
4 Binary Search Tree Node template BSTNode { DataType 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.
5
5 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
6
6 Inserting Nodes Into a BST (cont.) 37, 2, 45, 48, 41, 29, 20, 30, 49, 7 root 37
7
7 Inserting Nodes Into a BST (cont.) 2, 45, 48, 41, 29, 20, 30, 49, 7 root 37
8
8 Inserting Nodes Into a BST (cont.) 2, 45, 48, 41, 29, 20, 30, 49, 7 root 37
9
9 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
10
10 Inserting Nodes Into a BST (cont.) 2, 45, 48, 41, 29, 20, 30, 49, 7 root 37 2
11
11 Inserting Nodes Into a BST (cont.) 45, 48, 41, 29, 20, 30, 49, 7 root 37 2
12
12 Inserting Nodes Into a BST (cont.) 45, 48, 41, 29, 20, 30, 49, 7 root 37 2
13
13 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
14
14 Inserting Nodes Into a BST (cont.) 45, 48, 41, 29, 20, 30, 49, 7 root 37 2 45
15
15 Inserting Nodes Into a BST (cont.) 48, 41, 29, 20, 30, 49, 7 root 37 2 45
16
16 Inserting Nodes Into a BST (cont.) 48, 41, 29, 20, 30, 49, 7 root 37 2 45
17
17 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
18
18 Inserting Nodes Into a BST (cont.) 48, 41, 29, 20, 30, 49, 7 root 37 2 45 48 > 37, so look to the right
19
19 Inserting Nodes Into a BST (cont.) 48, 41, 29, 20, 30, 49, 7 root 37 2 45 48 > 37, so look to the right
20
20 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
21
21 Inserting Nodes Into a BST (cont.) 48, 41, 29, 20, 30, 49, 7 root 37 2 45 48 > 45, and 45 has no right child, so we insert 48 on the right of 45
22
22 Inserting Nodes Into a BST (cont.) 48, 41, 29, 20, 30, 49, 7 root 37 2 45 48
23
23 Inserting Nodes Into a BST (cont.) 41, 29, 20, 30, 49, 7 root 37 2 45 48
24
24 Inserting Nodes Into a BST (cont.) 41, 29, 20, 30, 49, 7 root 37 2 45 48
25
25 Inserting Nodes Into a BST (cont.) 41, 29, 20, 30, 49, 7 root 37 2 45 48 41 > 37, so look to the right
26
26 Inserting Nodes Into a BST (cont.) 41, 29, 20, 30, 49, 7 root 37 2 45 48
27
27 Inserting Nodes Into a BST (cont.) 41, 29, 20, 30, 49, 7 root 37 2 45 48 41 < 45, so look to the left – there is no left child, so insert
28
28 Inserting Nodes Into a BST (cont.) 41, 29, 20, 30, 49, 7 root 37 2 45 48 41
29
29 Inserting Nodes Into a BST (cont.) 29, 20, 30, 49, 7 root 37 2 45 48 41
30
30 Inserting Nodes Into a BST (cont.) 29, 20, 30, 49, 7 root 37 2 45 48 41
31
31 Inserting Nodes Into a BST (cont.) 29, 20, 30, 49, 7 root 37 2 45 48 41 29 < 37
32
32 Inserting Nodes Into a BST (cont.) 29, 20, 30, 49, 7 root 37 2 45 48 41
33
33 Inserting Nodes Into a BST (cont.) 29, 20, 30, 49, 7 root 37 2 45 48 41 29 > 2
34
34 Inserting Nodes Into a BST (cont.) 29, 20, 30, 49, 7 root 37 2 45 48 4129
35
35 Inserting Nodes Into a BST (cont.) 20, 30, 49, 7 root 37 2 45 48 4129
36
36 Inserting Nodes Into a BST (cont.) 20, 30, 49, 7 root 37 2 45 48 4129
37
37 Inserting Nodes Into a BST (cont.) 20, 30, 49, 7 root 37 2 45 48 4129 20 < 37
38
38 Inserting Nodes Into a BST (cont.) 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 > 2
40
40 Inserting Nodes Into a BST (cont.) 20, 30, 49, 7 root 37 2 45 48 4129
41
41 Inserting Nodes Into a BST (cont.) 20, 30, 49, 7 root 37 2 45 48 4129 20 < 29
42
42 Inserting Nodes Into a BST (cont.) 20, 30, 49, 7 root 37 2 45 48 4129 20
43
43 Inserting Nodes Into a BST (cont.) 30, 49, 7 root 37 2 45 48 4129 20
44
44 Inserting Nodes Into a BST (cont.) 30, 49, 7 root 37 2 45 48 4129 20
45
45 Inserting Nodes Into a BST (cont.) 30, 49, 7 root 37 2 45 48 4129 20 30 < 37
46
46 Inserting Nodes Into a BST (cont.) 30, 49, 7 root 37 2 45 48 4129 20
47
47 Inserting Nodes Into a BST (cont.) 30, 49, 7 root 37 2 45 48 4129 20 30 > 2
48
48 Inserting Nodes Into a BST (cont.) 30, 49, 7 root 37 2 45 48 4129 20
49
49 Inserting Nodes Into a BST (cont.) 30, 49, 7 root 37 2 45 48 4129 20 30 > 29
50
50 Inserting Nodes Into a BST (cont.) 30, 49, 7 root 37 2 45 48 4129 2030
51
51 Inserting Nodes Into a BST (cont.) 49, 7 root 37 2 45 48 4129 2030
52
52 Inserting Nodes Into a BST (cont.) 49, 7 root 37 2 45 48 4129 2030
53
53 Inserting Nodes Into a BST (cont.) 49, 7 root 37 2 45 48 4129 2030 49 > 37
54
54 Inserting Nodes Into a BST (cont.) 49, 7 root 37 2 45 48 4129 2030
55
55 Inserting Nodes Into a BST (cont.) 49, 7 root 37 2 45 48 4129 2030 49 > 45
56
56 Inserting Nodes Into a BST (cont.) 49, 7 root 37 2 45 48 4129 2030
57
57 Inserting Nodes Into a BST (cont.) 49, 7 root 37 2 45 48 4129 2030 49 > 48
58
58 Inserting Nodes Into a BST (cont.) 49, 7 root 37 2 45 48 4129 203049
59
59 Inserting Nodes Into a BST (cont.) 7 root 37 2 45 48 4129 203049
60
60 Inserting Nodes Into a BST (cont.) 7 root 37 2 45 48 4129 203049
61
61 Inserting Nodes Into a BST (cont.) 7 root 37 2 45 48 4129 203049 7 < 37
62
62 Inserting Nodes Into a BST (cont.) 7 root 37 2 45 48 4129 203049
63
63 Inserting Nodes Into a BST (cont.) 7 root 37 2 45 48 4129 203049 7 > 2
64
64 Inserting Nodes Into a BST (cont.) 7 root 37 2 45 48 4129 203049
65
65 Inserting Nodes Into a BST (cont.) 7 root 37 2 45 48 4129 203049 7 < 29
66
66 Inserting Nodes Into a BST (cont.) 7 root 37 2 45 48 4129 203049
67
67 Inserting Nodes Into a BST (cont.) 7 root 37 2 45 48 4129 203049 7 < 20
68
68 Inserting Nodes Into a BST (cont.) 7 root 37 2 45 48 4129 203049 7
69
69 Inserting Nodes Into a BST (cont.) root 37 2 45 48 4129 203049 7
70
70 Inserting Nodes Into a BST (cont.) root 37 2 45 48 4129 203049 All elements have been inserted 7
71
71 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
72
72 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 29 7
73
73 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 29 7
74
74 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 29 29 < 37 7
75
75 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 29 7
76
76 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 29 29 > 2 7
77
77 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 29 7
78
78 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
79
79 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 7
80
80 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 3 7
81
81 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 3 7
82
82 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 3 3 < 37 7
83
83 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 3 7
84
84 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 3 3 > 2 7
85
85 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 3 7
86
86 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 3 3 < 29 7
87
87 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 3 7
88
88 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 3 3 < 20 7
89
89 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 3 7
90
90 Searching for a Key in a BST (cont.) root 37 2 45 48 4129 203049 Key to search for: 3 3 < 7 7
91
91 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
92
92 Time Complexities If the binary search tree happens to be a complete binary tree: –the time for insertion is ( lg n ) –the time for the search is O( lg n ) –similar to swapping upwards or downwards through the heap However, we could run into some bad luck…
93
93 Bad Luck 2, 7, 20, 29, 30, 37, 41, 45, 48, 49 root 2 7 20 29 30 37 41 45 48 49 Exactly the same keys were inserted into this BST – but they were inserted in a different order (the order shown below)
94
94 Bad Luck (cont.) 2, 7, 20, 29, 30, 37, 41, 45, 48, 49 root 2 7 20 29 30 37 41 45 48 49 This is some bad luck, but a BST can be formed this way
95
95 Bad Luck (cont.) 2, 7, 20, 29, 30, 37, 41, 45, 48, 49 root 2 7 20 29 30 37 41 45 48 49 Using the “tightest” possible big-oh notation, the insertion and search time is O( n )
96
96 Balanced vs. Unbalanced If a BST takes ( lg n ) time for insertion, and O( lg n ) time for a search, we say it is a balanced binary search tree If a BST take O( n ) time for insertion and searching, we say it is an unbalanced binary search tree These definitions assume the tightest possible big-oh notation
97
97 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
98
98 Deletion Case 1: No Children root 37 2 45 48 4129 203049 Node 49 has no children – to delete it, we just remove it
99
99 Deletion Case 1: No Children (cont.) root 37 2 45 48 4129 2030
100
100 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
101
101 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
102
102 Deletion Case 2: One Child (cont.) root 37 2 45 4129 203049
103
103 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
104
104 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
105
105 Deletion Case 2: One Child (cont.) root 37 45 48 4129 203049
106
106 Deletion Case 3: Two Children root 37 2 45 48 4129 203049 Node 37 has two children…
107
107 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
108
108 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 to delete it, first we find the greatest node in its left subtree
109
109 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 First, we go to the left once, then follow the right pointers as far as we can
110
110 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 First, we go to the left once, then follow the right pointers as far as we can
111
111 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 First, we go to the left once, then follow the right pointers as far as we can
112
112 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 First, we go to the left once, then follow the right pointers as far as we can
113
113 Deletion Case 3: Two Children (cont.) root 37 2 45 48 4129 203049 Next, we copy the object at node 30 into node 37
114
114 Deletion Case 3: Two Children (cont.) root 37 2 45 48 4129 203049 Next, we copy the object at node 30 into node 37
115
115 Deletion Case 3: Two Children (cont.) root 30 2 45 48 4129 203049 Next, we copy the object at node 30 into node 37
116
116 Deletion Case 3: Two Children (cont.) root 30 2 45 48 4129 203049 Finally, we delete the lower red node using case 1 or case 2 deletion
117
117 Deletion Case 3: Two Children (cont.) root 30 2 45 48 4129 2049
118
118 Deletion Case 3: Two Children (cont.) root 30 2 45 48 4129 2049 Let’s delete node 30 now
119
119 Deletion Case 3: Two Children (cont.) root 30 2 45 48 4129 2049
120
120 Deletion Case 3: Two Children (cont.) root 30 2 45 48 4129 2049
121
121 Deletion Case 3: Two Children (cont.) root 30 2 45 48 4129 2049 The greatest node in the left subtree of node 30
122
122 Deletion Case 3: Two Children (cont.) root 30 2 45 48 4129 2049 The greatest node in the left subtree of node 30
123
123 Deletion Case 3: Two Children (cont.) root 29 2 45 48 4129 2049 The greatest node in the left subtree of node 30
124
124 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
125
125 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
126
126 Deletion Case 3: Two Children (cont.) root 29 2 45 48 41 2049
127
127 Deletion Time Complexity In all cases, we must find the node we wish to delete first, using the standard search method. Finding the greatest node in the left subtree is just a continuation of a path down the BST For balanced BST’s, the time complexity for deletion is O( lg n ) in all 3 cases For unbalanced BST’s, the time complexity is O( n ) in all 3 cases
128
128 Why Use BST’s? Hash tables can search in ( 1 ) time, so why use BST’s? BST’s have the ability to provide all keys in order, in ( n ) time To do so, it uses a recursive function called InOrder2, and a driver for the recursive function called InOrder…
129
129 1 template 2 bool BinarySearchTree::InOrder( Array & arr ) 3 { 4if ( size == 0 ) 5return false; 6arr.changeSize( size ); 7int i = 0; 8InOrder2( root, arr, i ); 9return true; 10 } The client uses the driver called InOrder, passing in an Array by reference, which will contain the objects in order by key after returning from InOrder Getting Elements In Order
130
130 1 template 2 bool BinarySearchTree::InOrder( Array & arr ) 3 { 4if ( size == 0 ) 5return false; 6arr.changeSize( size ); 7int i = 0; 8InOrder2( root, arr, i ); 9return true; 10 } If the BST has no elements, false is returned Getting Elements In Order (cont.)
131
131 1 template 2 bool BinarySearchTree::InOrder( Array & arr ) 3 { 4if ( size == 0 ) 5return false; 6arr.changeSize( size ); 7int i = 0; 8InOrder2( root, arr, i ); 9return true; 10 } The size of the Array is changed, so that it contains enough elements for all the nodes in the BST – the client may have set the size of the Array correctly, but we like to play it safe Getting Elements In Order (cont.)
132
132 1 template 2 bool BinarySearchTree::InOrder( Array & arr ) 3 { 4if ( size == 0 ) 5return false; 6arr.changeSize( size ); 7int i = 0; 8InOrder2( root, arr, i ); 9return true; 10 } i is used to index the Array Getting Elements In Order (cont.)
133
133 1 template 2 bool BinarySearchTree::InOrder( Array & arr ) 3 { 4if ( size == 0 ) 5return false; 6arr.changeSize( size ); 7int i = 0; 8InOrder2( root, arr, i ); 9return true; 10 } The recursive function InOrder2 is called, passing arr by reference – when the top-level InOrder2 returns, arr will contain the objects with keys in sorted order Getting Elements In Order (cont.)
134
134 1 template 2 bool BinarySearchTree::InOrder( Array & arr ) 3 { 4if ( size == 0 ) 5return false; 6arr.changeSize( size ); 7int i = 0; 8InOrder2( root, arr, i ); 9return true; 10 } So let’s now focus on the InOrder2 function… Getting Elements In Order (cont.)
135
135 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } Getting Elements In Order (cont.)
136
136 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } This is the only line which places info in the array… Getting Elements In Order (cont.)
137
137 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } then i is incremented Getting Elements In Order (cont.)
138
138 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } i is passed by reference, so every time it is incremented, the calling function knows about it Getting Elements In Order (cont.)
139
139 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } The base case occurs when ptr is NULL – just returns Getting Elements In Order (cont.)
140
140 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } There are two recursive calls under the if – the first advances the pointer to the left child… Getting Elements In Order (cont.)
141
141 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } and the second advances the pointer to the right child Getting Elements In Order (cont.)
142
142 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } Notice that this will be the same ptr in both cases Getting Elements In Order (cont.)
143
143 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } Notice that each recursive call approaches the base case… Getting Elements In Order (cont.)
144
144 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } it goes down one level through the tree, and so it must get closer to the case where ptr->left or ptr- >right is NULL Getting Elements In Order (cont.)
145
145 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } If the BST contains only one node, does InOrder2 work? Getting Elements In Order (cont.)
146
146 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } In this case, the root node is the only node – the left and right pointers of the root node will be set to NULL. Getting Elements In Order (cont.)
147
147 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } Getting Elements In Order (cont.)
148
148 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } ptr->left is NULL, so NULL is passed into ptr of the new InOrder2 function that is made Getting Elements In Order (cont.)
149
149 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } Since ptr is NULL in the new InOrder2 function, it will return right away Getting Elements In Order (cont.)
150
150 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } Getting Elements In Order (cont.)
151
151 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } i is still 0 from the driver – ptr is the root at this level – so the info at the root is placed into arr[ 0 ] Getting Elements In Order (cont.)
152
152 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } i becomes 1 Getting Elements In Order (cont.)
153
153 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } ptr->right is NULL – thus, the recursive function call immediately returns as before Getting Elements In Order (cont.)
154
154 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } InOrder2 returns back to the driver with the correct array Getting Elements In Order (cont.)
155
155 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } InOrder2 works correctly when there is only one node Getting Elements In Order (cont.)
156
156 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } So InOrder2 works correctly when there is only one node in the BST or the BST is empty (root is NULL) Getting Elements In Order (cont.)
157
157 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } Thus, it will work for a larger tree with 0 or 1 nodes in the left subtree, and 0 or 1 nodes in the right subtree, etc., etc. Getting Elements In Order (cont.)
158
158 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } Consider the general case: p nodes in the left subtree and r nodes in the right subtree Getting Elements In Order (cont.)
159
159 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } We assume that InOrder2 does what it is supposed to do Getting Elements In Order (cont.)
160
160 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } The p nodes in the left subtree are all less than the root node, and will occupy the first p positions of the array. Getting Elements In Order (cont.)
161
161 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } i is always incremented after adding an element, so… Getting Elements In Order (cont.)
162
162 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } The root writes its info correctly in position p + 1 of the array Getting Elements In Order (cont.)
163
163 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } Then, the last r nodes of the right subtree (all greater than the root) are written in the last r positions of the array Getting Elements In Order (cont.)
164
164 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } Again, we assume InOrder2 does what it is supposed to do Getting Elements In Order (cont.)
165
165 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } Thus, if we assume the recursive call of InOrder2 does what it is supposed to do, we have established the correctness… Getting Elements In Order (cont.)
166
166 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } since InOrder2 works with smaller cases, we build larger cases from the smaller cases, using the smaller cases as left and right subtrees Getting Elements In Order (cont.)
167
167 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } How do we know the time complexity is ( n )? Getting Elements In Order (cont.)
168
168 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } InOrder2 is called once from the driver. Then, for each node in the tree, 2 calls to InOrder2 are made, giving us a total of 2n + 1 calls. Getting Elements In Order (cont.)
169
169 1 template 2 void BinarySearchTree::InOrder2( 3 BSTNode *ptr, Array & arr, int & i ) 4 { 5if ( ptr != NULL ) { 6InOrder2( ptr->left, arr, i ); 7arr[ i ] = ptr->info; 8i++; 9InOrder2( ptr->right, arr, i ); 10} 11 } Since InOrder2 is called a total of 2n + 1 times, it is ( n ) Getting Elements In Order (cont.)
170
170 Ensuring a Balanced BST Various schemes have been used to ensure a BST is balanced –red-black trees –AVL trees Insertion, searching, and deletion are all guaranteed to be O( lg n ), using the tightest big-oh notation
171
171 Ensuring a Balanced BST (cont.) The BST is faster, on average, than the red-black / AVL trees –BST’s are usually balanced –more work is required to ensure balancing However, the red-black / AVL trees give consistent performance –faster when BST’s are unbalanced –important in time-critical applications
172
172 Comparison of BST to Doubly-Linked List The hash table implementation of a doubly-linked list can be an alternative –under uniform hashing, a search can be done in ( 1 ) time –an insertion is done in ( 1 ) time (inserting at the head of the list) –under uniform hashing, a deletion is done in ( 1 ) time –what about providing elements in order?
173
173 Comparison of BST to Doubly-Linked List (cont.) A linked list can be sorted without affecting the time complexity of the sorting algorithm (as in the previous chapter) It generally takes ( n lg n ) time to sort a linked list It is possible to sort in ( n ) time (under favorable conditions) Once sorted, the elements can be provided in order
174
174 Since BST’s are usually balanced, it generally takes about ( n lg n ) time to insert n elements into a BST It takes ( n ) time to insert n elements at the head of a doubly-linked list The one to select, BST or doubly-linked list, depends on the situation one is working with (as usual) Comparison of BST to Doubly-Linked List (cont.)
175
175 Graphs Graphs are a very general data structure A graph consists of a set of nodes called vertices Any vertex can point to any number of other vertices It is possible that no vertex in the graph points to any other vertex Each vertex may point to every other vertex, even if there are thousands of vertices
176
176 A Directed Graph (Digraph) A D B C E F Each pointer is called an edge
177
177 An Undirected Graph A D B C E F Each edge points in both directions – ex: A points to D and D points to A
178
178 Another Digraph A D B C E F Nodes A and F point to each other – it is considered improper to draw a single undirected edge between them
179
179 Weighted Graph Graphville Node Town Vertex City Pointerburgh Builder’s Paradise Binary Tree Valley 3 8 4 4 10 4 2
180
180 Graph Implementation A vertex A is said to be adjacent to a vertex B if there is an edge pointing from A to B Graphs can be implemented in a couple of popular ways: –adjacency matrix –adjacency list
181
181 Adjacency Matrix Nodes are given a key from 0 to n – 1 The adjacency matrix is a 2-dimensional array of bool type variables
182
182 F T T F F T F F T T T F F F F T F F F T F T T T F F F F F T 012345012345 Adjacency Matrix (cont.) 0 1 2 3 4 5 T T F F F F
183
183 F T T F F T F F T T T F F F F T F F F T F T T T F F F F F T 012345012345 Adjacency Matrix (cont.) 0 1 2 3 4 5 T T F F F F The row numbers give the vertex number of the vertex that an edge is pointing from
184
184 F T T F F T F F T T T F F F F T F F F T F T T T F F F F F T 012345012345 Adjacency Matrix (cont.) 0 1 2 3 4 5 T T F F F F Example: Node 1 points to Node 2 (set to T)
185
185 F T T F F T F F T T T F F F F T F F F T F T T T F F F F F T 012345012345 Adjacency Matrix (cont.) 0 1 2 3 4 5 T T F F F F Example: But Node 2 doesn’t point to Node 1 (set to F)
186
186 F T T F F T F F T T T F F F F T F F F T F T T T F F F F F T 012345012345 Adjacency Matrix (cont.) 0 1 2 3 4 5 T T F F F F Note that we can construct a graph from the adjacency matrix – the vertices may not be drawn in the same locations as the original graph, but the connections will be the same
187
187 Adjacency List An adjacency list is an array of linked lists The vertices are numbered 0 through n – 1 Each index in the array corresponds to the number of a vertex The vertex (with an index number) is adjacent to every node in the linked list at that index
188
188 Adjacency List (cont.) 1 2 5 4 3 5 1 3 012345012345
189
189 Adjacency List (cont.) 1 2 5 4 3 5 1 3 012345012345 Vertex 1 is adjacent to vertex 2, and vertex 1 is also adjacent to vertex 5
190
190 Adjacency List (cont.) 1 2 5 4 3 5 1 3 012345012345 Note: vertex 2 may not connect to vertex 5 in the graph: 1 2 5
191
191 Adjacency List (cont.) 1 2 5 4 3 5 1 3 012345012345 Vertex 3 has an empty linked list – it is not adjacent to any other vertices
192
192 Adjacency List for Weighted Graph 1 3 012345012345 2 4 3 8 0 3 3 4 0 4 4 4 5 10 0 8 1 4 5 2 2 4 2 10 3 2 Red font is for vertex numbers, black font is for weights
193
193 Vertex Info Ordinarily, the vertex info is not stored in a linked list node of an adjacency list The vertex info size may be huge, and many duplicates of it would be stored throughout the adjacency list, wasting space Instead, a separate array contains the vertex info objects; each index corresponds to a vertex number for easy look-up
194
194 Adjacency Matrix vs. Adjacency List The speed of the adjacency matrix or the adjacency list depends on the algorithm –some algorithms need to know if there is a direct connection between two specific vertices – the adjacency matrix would be faster –some algorithms are written to process the linked list of an adjacency list, node by node – the adjacency list would be faster
195
195 Adjacency Matrix vs. Adjacency List (cont.) When both seem equally fast for a certain algorithm, then we consider memory usage We will consider the space complexity of each implementation Space complexities are like time complexities, but they tell us the effects on memory space usage as the problem size is varied
196
196 An array of vertex info is used for each implementation, which is ( n ) In the adjacency matrix, each dimension is n, so the spatial complexity is ( n 2 ) In the adjacency list, there are n elements in the array, giving a spatial complexity of ( n ) for the array Adjacency Matrix vs. Adjacency List (cont.)
197
197 Note that each edge corresponds to a linked list node in the adjacency list There can be no more than n( n – 1 ) edges in a graph, so the spatial complexity for the linked list nodes is O( n 2 ) the total spatial complexity for the adjacency list is O( n 2 ) Adjacency Matrix vs. Adjacency List (cont.)
198
198 Both of the spatial complexities for the adjacency matrix and the adjacency list absorb the ( n ) spatial complexity used in the vertex info array The spatial complexity of the adjacency list really depends on whether the graph is sparse or dense Adjacency Matrix vs. Adjacency List (cont.)
199
199 A sparse graph does not have that many edges relative to the number of vertices – if the number of edges is less than or equal to n, then the spacial complexity of the adjacency list is ( n ) In a dense graph, there may be close to n 2 edges, and then the spatial complexity of the adjacency list is ( n 2 ), the same as that for the adjacency matrix Adjacency Matrix vs. Adjacency List (cont.)
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.