1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 15 Other Data Structures Jeffrey S. Childs Clarion University of PA © 2008, Prentice Hall.

Slides:



Advertisements
Similar presentations
CS16: Introduction to Data Structures & Algorithms
Advertisements

Introduction to Algorithms Quicksort
COL 106 Shweta Agrawal and Amit Kumar
Binary Trees CSC 220. Your Observations (so far data structures) Array –Unordered Add, delete, search –Ordered Linked List –??
Comp 122, Spring 2004 Binary Search Trees. btrees - 2 Comp 122, Spring 2004 Binary Trees  Recursive definition 1.An empty tree is a binary tree 2.A node.
Chapter 4: Trees Part II - AVL Tree
AVL Trees COL 106 Amit Kumar Shweta Agrawal Slide Courtesy : Douglas Wilhelm Harder, MMath, UWaterloo
1 abstract containers hierarchical (1 to many) graph (many to many) first ith last sequence/linear (1 to 1) set.
Binary Trees. DCS – SWC 2 Binary Trees Sets and Maps in Java are also available in tree-based implementations A Tree is – in this context – a data structure.
1 A Two-Level Binary Expression ‘-’ ‘8’ ‘5’ treePtr INORDER TRAVERSAL : has value 3 PREORDER TRAVERSAL: POSTORDER TRAVERSAL: 8 5 -
Tirgul 10 Rehearsal about Universal Hashing Solving two problems from theoretical exercises: –T2 q. 1 –T3 q. 2.
Data Structures Topic #9. Today’s Agenda Continue Discussing Trees Examine the algorithm to insert Examine the algorithm to remove Begin discussing efficiency.
BST Data Structure A BST node contains: A BST contains
Chapter 13 Binary Search Trees. Copyright © 2005 Pearson Addison-Wesley. All rights reserved Chapter Objectives Define a binary search tree abstract.
1 abstract containers hierarchical (1 to many) graph (many to many) first ith last sequence/linear (1 to 1) set.
General Trees and Variants CPSC 335. General Trees and transformation to binary trees B-tree variants: B*, B+, prefix B+ 2-4, Horizontal-vertical, Red-black.
Chapter 12 Trees. Copyright © 2005 Pearson Addison-Wesley. All rights reserved Chapter Objectives Define trees as data structures Define the terms.
Data Structures Using C++ 2E Chapter 11 Binary Trees and B-Trees.
Ch. 13: Balanced Search Trees Symbol table: insert, delete, find, pred, succ, sort,… Binary Search Tree review: What is a BST? binary tree with a key at.
C++ Programming: Program Design Including Data Structures, Third Edition Chapter 20: Binary Trees.
C o n f i d e n t i a l HOME NEXT Subject Name: Data Structure Using C Unit Title: Trees.
More Trees COL 106 Amit Kumar and Shweta Agrawal Most slides courtesy : Douglas Wilhelm Harder, MMath, UWaterloo
1 HEAPS & PRIORITY QUEUES Array and Tree implementations.
1 Search Trees - Motivation Assume you would like to store several (key, value) pairs in a data structure that would support the following operations efficiently.
CSCE 3110 Data Structures & Algorithm Analysis Binary Search Trees Reading: Chap. 4 (4.3) Weiss.
Data Structures - CSCI 102 Binary Tree In binary trees, each Node can point to two other Nodes and looks something like this: template class BTNode { public:
Review Binary Tree Binary Tree Representation Array Representation Link List Representation Operations on Binary Trees Traversing Binary Trees Pre-Order.
Compiled by: Dr. Mohammad Alhawarat BST, Priority Queue, Heaps - Heapsort CHAPTER 07.
Advanced Algorithms Analysis and Design Lecture 8 (Continue Lecture 7…..) Elementry Data Structures By Engr Huma Ayub Vine.
1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 8 Stacks and Queues Jeffrey S. Childs Clarion University of PA © 2008, Prentice Hall.
C++ Classes and Data Structures Jeffrey S. Childs
Searching: Binary Trees and Hash Tables CHAPTER 12 6/4/15 Nyhoff, ADTs, Data Structures and Problem Solving with C++, Second Edition, © 2005 Pearson Education,
Binary Trees Chapter 10. Introduction Previous chapter considered linked lists –nodes connected by two or more links We seek to organize data in a linked.
1 Trees A tree is a data structure used to represent different kinds of data and help solve a number of algorithmic problems Game trees (i.e., chess ),
INTRODUCTION TO BINARY TREES P SORTING  Review of Linear Search: –again, begin with first element and search through list until finding element,
1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 13 Recursion Jeffrey S. Childs Clarion University of PA © 2008, Prentice Hall.
BINARY SEARCH TREE. Binary Trees A binary tree is a tree in which no node can have more than two children. In this case we can keep direct links to the.
Chapter 6 Binary Trees. 6.1 Trees, Binary Trees, and Binary Search Trees Linked lists usually are more flexible than arrays, but it is difficult to use.
Binary Trees, Binary Search Trees RIZWAN REHMAN CENTRE FOR COMPUTER STUDIES DIBRUGARH UNIVERSITY.
1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 14 Introduction to Sorting Algorithms Jeffrey S. Childs Clarion University of PA © 2008, Prentice.
1 Binary Trees Informal defn: each node has 0, 1, or 2 children Informal defn: each node has 0, 1, or 2 children Formal defn: a binary tree is a structure.
P p Chapter 10 has several programming projects, including a project that uses heaps. p p This presentation shows you what a heap is, and demonstrates.
1 Chapter 17 Object-Oriented Data Structures. 2 Objectives F To describe what a data structure is (§17.1). F To explain the limitations of arrays (§17.1).
CSC 211 Data Structures Lecture 13
1 Chapter 10 Trees. 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.
CMSC 341 B- Trees D. Frey with apologies to Tom Anastasio.
Binary Trees Chapter 10. Introduction Previous chapter considered linked lists –nodes connected by two or more links We seek to organize data in a linked.
Week 10 - Friday.  What did we talk about last time?  Graph representations  Adjacency matrix  Adjacency lists  Depth first search.
Binary Search Trees (BST)
Tree Data Structures. Heaps for searching Search in a heap? Search in a heap? Would have to look at root Would have to look at root If search item smaller.
AVL Trees and Heaps. AVL Trees So far balancing the tree was done globally Basically every node was involved in the balance operation Tree balancing can.
Week 15 – Wednesday.  What did we talk about last time?  Review up to Exam 1.
Copyright © 2012 Pearson Education, Inc. Chapter 20: Binary Trees.
Data Structures Using C++ 2E Chapter 11 Binary Trees.
Binary Search Trees.  Understand tree terminology  Understand and implement tree traversals  Define the binary search tree property  Implement binary.
1 Chapter 6 Methods for Making Data Structures. 2 Dynamic Arrays in Data Structures In almost every data structure, we want functions for inserting and.
Search: Binary Search Trees Dr. Yingwu Zhu. Review: Linear Search Collection of data items to be searched is organized in a list x 1, x 2, … x n – Assume.
Chapter 11. Chapter Summary  Introduction to trees (11.1)  Application of trees (11.2)  Tree traversal (11.3)  Spanning trees (11.4)
Hashing Exercises.
COMP 103 Binary Search Trees.
Lecture 25 Splay Tree Chapter 10 of textbook
Chapter 20: Binary Trees.
Map interface Empty() - return true if the map is empty; else return false Size() - return the number of elements in the map Find(key) - if there is an.
Monday, April 16, 2018 Announcements… For Today…
Chapter 21: Binary Trees.
C++ Classes and Data Structures Jeffrey S. Childs
A Robust Data Structure
Instructor: Dr. Michael Geiger Spring 2017 Lecture 30: Sorting & heaps
Data Structures Using C++ 2E
Presentation transcript:

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 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 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 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 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 Inserting Nodes Into a BST (cont.) 37, 2, 45, 48, 41, 29, 20, 30, 49, 7 root 37

7 Inserting Nodes Into a BST (cont.) 2, 45, 48, 41, 29, 20, 30, 49, 7 root 37

8 Inserting Nodes Into a BST (cont.) 2, 45, 48, 41, 29, 20, 30, 49, 7 root 37

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 Inserting Nodes Into a BST (cont.) 2, 45, 48, 41, 29, 20, 30, 49, 7 root 37 2

11 Inserting Nodes Into a BST (cont.) 45, 48, 41, 29, 20, 30, 49, 7 root 37 2

12 Inserting Nodes Into a BST (cont.) 45, 48, 41, 29, 20, 30, 49, 7 root 37 2

13 Inserting Nodes Into a BST (cont.) 45, 48, 41, 29, 20, 30, 49, 7 root > 37, so insert it at the right of 37

14 Inserting Nodes Into a BST (cont.) 45, 48, 41, 29, 20, 30, 49, 7 root

15 Inserting Nodes Into a BST (cont.) 48, 41, 29, 20, 30, 49, 7 root

16 Inserting Nodes Into a BST (cont.) 48, 41, 29, 20, 30, 49, 7 root

17 Inserting Nodes Into a BST (cont.) 48, 41, 29, 20, 30, 49, 7 root When comparing, we always start at the root node

18 Inserting Nodes Into a BST (cont.) 48, 41, 29, 20, 30, 49, 7 root > 37, so look to the right

19 Inserting Nodes Into a BST (cont.) 48, 41, 29, 20, 30, 49, 7 root > 37, so look to the right

20 Inserting Nodes Into a BST (cont.) 48, 41, 29, 20, 30, 49, 7 root This time, there is a node already to the right of the root node. We then compare 48 to this node

21 Inserting Nodes Into a BST (cont.) 48, 41, 29, 20, 30, 49, 7 root > 45, and 45 has no right child, so we insert 48 on the right of 45

22 Inserting Nodes Into a BST (cont.) 48, 41, 29, 20, 30, 49, 7 root

23 Inserting Nodes Into a BST (cont.) 41, 29, 20, 30, 49, 7 root

24 Inserting Nodes Into a BST (cont.) 41, 29, 20, 30, 49, 7 root

25 Inserting Nodes Into a BST (cont.) 41, 29, 20, 30, 49, 7 root > 37, so look to the right

26 Inserting Nodes Into a BST (cont.) 41, 29, 20, 30, 49, 7 root

27 Inserting Nodes Into a BST (cont.) 41, 29, 20, 30, 49, 7 root < 45, so look to the left – there is no left child, so insert

28 Inserting Nodes Into a BST (cont.) 41, 29, 20, 30, 49, 7 root

29 Inserting Nodes Into a BST (cont.) 29, 20, 30, 49, 7 root

30 Inserting Nodes Into a BST (cont.) 29, 20, 30, 49, 7 root

31 Inserting Nodes Into a BST (cont.) 29, 20, 30, 49, 7 root < 37

32 Inserting Nodes Into a BST (cont.) 29, 20, 30, 49, 7 root

33 Inserting Nodes Into a BST (cont.) 29, 20, 30, 49, 7 root > 2

34 Inserting Nodes Into a BST (cont.) 29, 20, 30, 49, 7 root

35 Inserting Nodes Into a BST (cont.) 20, 30, 49, 7 root

36 Inserting Nodes Into a BST (cont.) 20, 30, 49, 7 root

37 Inserting Nodes Into a BST (cont.) 20, 30, 49, 7 root < 37

38 Inserting Nodes Into a BST (cont.) 20, 30, 49, 7 root

39 Inserting Nodes Into a BST (cont.) 20, 30, 49, 7 root > 2

40 Inserting Nodes Into a BST (cont.) 20, 30, 49, 7 root

41 Inserting Nodes Into a BST (cont.) 20, 30, 49, 7 root < 29

42 Inserting Nodes Into a BST (cont.) 20, 30, 49, 7 root

43 Inserting Nodes Into a BST (cont.) 30, 49, 7 root

44 Inserting Nodes Into a BST (cont.) 30, 49, 7 root

45 Inserting Nodes Into a BST (cont.) 30, 49, 7 root < 37

46 Inserting Nodes Into a BST (cont.) 30, 49, 7 root

47 Inserting Nodes Into a BST (cont.) 30, 49, 7 root > 2

48 Inserting Nodes Into a BST (cont.) 30, 49, 7 root

49 Inserting Nodes Into a BST (cont.) 30, 49, 7 root > 29

50 Inserting Nodes Into a BST (cont.) 30, 49, 7 root

51 Inserting Nodes Into a BST (cont.) 49, 7 root

52 Inserting Nodes Into a BST (cont.) 49, 7 root

53 Inserting Nodes Into a BST (cont.) 49, 7 root > 37

54 Inserting Nodes Into a BST (cont.) 49, 7 root

55 Inserting Nodes Into a BST (cont.) 49, 7 root > 45

56 Inserting Nodes Into a BST (cont.) 49, 7 root

57 Inserting Nodes Into a BST (cont.) 49, 7 root > 48

58 Inserting Nodes Into a BST (cont.) 49, 7 root

59 Inserting Nodes Into a BST (cont.) 7 root

60 Inserting Nodes Into a BST (cont.) 7 root

61 Inserting Nodes Into a BST (cont.) 7 root < 37

62 Inserting Nodes Into a BST (cont.) 7 root

63 Inserting Nodes Into a BST (cont.) 7 root > 2

64 Inserting Nodes Into a BST (cont.) 7 root

65 Inserting Nodes Into a BST (cont.) 7 root < 29

66 Inserting Nodes Into a BST (cont.) 7 root

67 Inserting Nodes Into a BST (cont.) 7 root < 20

68 Inserting Nodes Into a BST (cont.) 7 root

69 Inserting Nodes Into a BST (cont.) root

70 Inserting Nodes Into a BST (cont.) root All elements have been inserted 7

71 Searching for a Key in a BST root Searching for a key in a BST uses the same logic 7

72 Searching for a Key in a BST (cont.) root Key to search for: 29 7

73 Searching for a Key in a BST (cont.) root Key to search for: 29 7

74 Searching for a Key in a BST (cont.) root Key to search for: < 37 7

75 Searching for a Key in a BST (cont.) root Key to search for: 29 7

76 Searching for a Key in a BST (cont.) root Key to search for: > 2 7

77 Searching for a Key in a BST (cont.) root Key to search for: 29 7

78 Searching for a Key in a BST (cont.) root Key to search for: == 29 FOUND IT! 7

79 Searching for a Key in a BST (cont.) root

80 Searching for a Key in a BST (cont.) root Key to search for: 3 7

81 Searching for a Key in a BST (cont.) root Key to search for: 3 7

82 Searching for a Key in a BST (cont.) root Key to search for: 3 3 < 37 7

83 Searching for a Key in a BST (cont.) root Key to search for: 3 7

84 Searching for a Key in a BST (cont.) root Key to search for: 3 3 > 2 7

85 Searching for a Key in a BST (cont.) root Key to search for: 3 7

86 Searching for a Key in a BST (cont.) root Key to search for: 3 3 < 29 7

87 Searching for a Key in a BST (cont.) root Key to search for: 3 7

88 Searching for a Key in a BST (cont.) root Key to search for: 3 3 < 20 7

89 Searching for a Key in a BST (cont.) root Key to search for: 3 7

90 Searching for a Key in a BST (cont.) root Key to search for: 3 3 < 7 7

91 Searching for a Key in a BST (cont.) root 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 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 Bad Luck 2, 7, 20, 29, 30, 37, 41, 45, 48, 49 root Exactly the same keys were inserted into this BST – but they were inserted in a different order (the order shown below)

94 Bad Luck (cont.) 2, 7, 20, 29, 30, 37, 41, 45, 48, 49 root This is some bad luck, but a BST can be formed this way

95 Bad Luck (cont.) 2, 7, 20, 29, 30, 37, 41, 45, 48, 49 root Using the “tightest” possible big-oh notation, the insertion and search time is O( n )

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 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 Deletion Case 1: No Children root Node 49 has no children – to delete it, we just remove it

99 Deletion Case 1: No Children (cont.) root

100 Deletion Case 2: One Child root Node 48 has one child – to delete it, we just splice it out

101 Deletion Case 2: One Child (cont.) root Node 48 has one child – to delete it, we just splice it out

102 Deletion Case 2: One Child (cont.) root

103 Deletion Case 2: One Child (cont.) root Another example: node 2 has one child – to delete it we also splice it out

104 Deletion Case 2: One Child (cont.) root Another example: node 2 has one child – to delete it we also splice it out

105 Deletion Case 2: One Child (cont.) root

106 Deletion Case 3: Two Children root Node 37 has two children…

107 Deletion Case 3: Two Children (cont.) root to delete it, first we find the greatest node in its left subtree

108 Deletion Case 3: Two Children (cont.) root 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 Deletion Case 3: Two Children (cont.) root 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 Deletion Case 3: Two Children (cont.) root 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 Deletion Case 3: Two Children (cont.) root 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 Deletion Case 3: Two Children (cont.) root 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 Deletion Case 3: Two Children (cont.) root Next, we copy the object at node 30 into node 37

114 Deletion Case 3: Two Children (cont.) root Next, we copy the object at node 30 into node 37

115 Deletion Case 3: Two Children (cont.) root Next, we copy the object at node 30 into node 37

116 Deletion Case 3: Two Children (cont.) root Finally, we delete the lower red node using case 1 or case 2 deletion

117 Deletion Case 3: Two Children (cont.) root

118 Deletion Case 3: Two Children (cont.) root Let’s delete node 30 now

119 Deletion Case 3: Two Children (cont.) root

120 Deletion Case 3: Two Children (cont.) root

121 Deletion Case 3: Two Children (cont.) root The greatest node in the left subtree of node 30

122 Deletion Case 3: Two Children (cont.) root The greatest node in the left subtree of node 30

123 Deletion Case 3: Two Children (cont.) root The greatest node in the left subtree of node 30

124 Deletion Case 3: Two Children (cont.) root This time, the lower red node has a child – to delete it we use case 2 deletion

125 Deletion Case 3: Two Children (cont.) root This time, the lower red node has a child – to delete it we use case 2 deletion

126 Deletion Case 3: Two Children (cont.) root

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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 A Directed Graph (Digraph) A D B C E F Each pointer is called an edge

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 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 Weighted Graph Graphville Node Town Vertex City Pointerburgh Builder’s Paradise Binary Tree Valley

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 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 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 Adjacency Matrix (cont.) T T F F F F

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 Adjacency Matrix (cont.) T T F F F F The row numbers give the vertex number of the vertex that an edge is pointing from

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 Adjacency Matrix (cont.) T T F F F F Example: Node 1 points to Node 2 (set to T)

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 Adjacency Matrix (cont.) T T F F F F Example: But Node 2 doesn’t point to Node 1 (set to F)

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 Adjacency Matrix (cont.) 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 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 Adjacency List (cont.)

189 Adjacency List (cont.) Vertex 1 is adjacent to vertex 2, and vertex 1 is also adjacent to vertex 5

190 Adjacency List (cont.) Note: vertex 2 may not connect to vertex 5 in the graph: 1 2 5

191 Adjacency List (cont.) Vertex 3 has an empty linked list – it is not adjacent to any other vertices

192 Adjacency List for Weighted Graph Red font is for vertex numbers, black font is for weights

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 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 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 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 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 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 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.)