CS2420: Lecture 17 Vladimir Kulyukin Computer Science Department Utah State University
Outline Trees (Chapter 4)
Tree Traversals InOrder traversal PreOrder traversal PostOrder traversal Level traversal
InOrder Traversal If the current node is not empty, –Traverse the left sub-tree; –Traverse the current node; –Traverse the right sub-tree.
InOrder Traversal in C++ template void processNode(CBinaryTreeNode *node) { // some code that processes the node somehow; } // We assume that we have implemented the getter and setter methods // for CBinaryTreeNode. template class CBinaryTreeNode { public: CBinaryTreeNode *getLeftChild() const { …} CBinaryTreeNode *getRightChild() const { … } void setLeftChild() { … } void setRightChild() { … } };
InOrder Traversal in C++ template void CBinaryTree ::inOrder(CBinaryTreeNode *node) { if ( node != NULL ) { inOrder(node->getLeftChild()); processNode(node); inOrder(node->getRightChild()); }
PreOrder Traversal If the current node is not empty, –Traverse the current node; –Traverse the left sub-tree; –Traverse the right sub-tree.
PreOrder Traversal in C++ template void CBinaryTree ::preOrder(CBinaryTreeNode *node) { if ( node != NULL ) { processNode(node); preOrder(node->getLeftChild()); preOrder(node->getRightChild()); }
PostOrder Traversal If the current node is not empty, –Traverse the left sub-tree; –Traverse the right sub-tree; –Traverse the current node.
PostOrder Traversal in C++ template void CBinaryTree ::postOrder(CBinaryTreeNode *node) { if ( node != NULL ) { postOrder(node->getLeftChild()); postOrder(node->getRightChild()); processNode(node); }
Level Traversal Initialize a queue of binary tree nodes. Add the root to the queue. While the queue is not empty –Pop the node from the queue; –Process the node; –If the popped node’s left child is not empty, add it to the queue; –If the popped node’s right child is not empty, add it to the queue; –Decide what to do with the popped node.
Deleting a Binary Tree template void CBinaryTree ::deleteTree(CBinaryTreeNode *node) { if ( node != NULL ) { deleteTree(node->GetLeftChild()); deleteTree(node->GetRightChild()); delete node; }
Basic Questions 3 and 4 from Lecture 1 How can I store/organize data efficiently? How can I retrieve/search data efficiently?
Collections and Dictionaries A Collection/Dictionary has a set of N elements each of which is indexed under a possibly unique key. The task of a collection/dictionary data structure is to insert/delete/retrieve an element given its key in the most efficient way.
Collections Lists, arrays, queues, and stacks are collections. List –Insertion: O(N); Deletion: O(N); Search: O(N). Array –Insertion: O(N); Deletion: O(N); Search: O(1). Queue –Insertion: O(1); Limited Deletion: O(1); Search: Not Available. Stack –Insertion: O(1): Limited Deletion: O(1); Search: Not Available.
Binary Search Tree: A Collection A Binary Search Tree (BST) is an empty binary tree. A BST is a non-empty binary tree such that –The keys in the left sub-tree are smaller than the root’s key; –The keys in the right sub-tree are larger than the root’s key; –The left and right sub-trees are BSTs.
Binary Search Tree ≠ Binary Tree Binary Search Tree ≠ Binary Tree. Every binary search tree is a binary tree. But not every binary tree is a binary search tree.
Example A BST Not A BST
BST with Duplicates If the key comparison is relaxed to =, the BST will contain duplicates. Two implementations of BST with duplicates: –Linked nodes; –Duplicate counters.
BT Node: Version 1 KEY DATA LEFT CHILD PTR RIGHT CHILD PTR
BT Node: Version 1.A KEY DATA LEFT CHILD PTR RIGHT CHILD PTR Key and Data are of the same type.
BT Node: Version 1.A template class CBinaryTreeNode { friend void ProcessNode(CBinaryTreeNode *node); protected: T m_Key; T m_Data; CBinaryTreeNode * m_LeftChild; CBinaryTreeNode * m_RightChild; public: CBinaryTreeNode * GetLeftChild() const; CBinaryTreeNode * GetRightChild() const; void SetLeftChild(CBinaryTreeNode *node); void SetRightChild(CBinaryTreeNode *node); T GetData() const { return m_Data; } T GetKey() const { return m_Key; } };
BT Node: Version 1.B KEY DATA LEFT CHILD PTR RIGHT CHILD PTR Key and Data are different types.
BT Node: Version 1.B template class CBinaryTreeNode { friend void ProcessNode(CBinaryTreeNode *node); protected: Key m_Key; Data m_Data; CBinaryTreeNode * m_LeftChild; CBinaryTreeNode * m_RightChild; public: CBinaryTreeNode * GetLeftChild() const; CBinaryTreeNode * GetRightChild() const; void SetLeftChild(CBinaryTreeNode *node); void SetRightChild(CBinaryTreeNode *node); Data GetData() const { return m_Data; } Key GetKey() const { return m_Key; } };
BT Node: Version 2 KEY = DATA LEFT CHILD PTR RIGHT CHILD PTR
BT Node: Version 2 template class CBinaryTreeNode { protected: T m_Data; CBinaryTreeNode * m_LeftChild; CBinaryTreeNode * m_RightChild; public: CBinaryTreeNode(); CBinaryTreeNode(const T& data); CBinaryTreeNode(const T& data, CBinaryTreeNode *left, CBinaryTreeNode *right); CBinaryTreeNode * GetLeftChild() const; CBinaryTreeNode * GetRightChild() const; void SetLeftChild(CBinaryTreeNode *node); void SetRightChild(CBinaryTreeNode *node); T GetData() const { return m_Data; } };
Binary Search Tree Interface template class CBinarySearchTree : public CBinaryTree { protected: CBinaryTreeNode *m_Current; int m_Size; // number of nodes in the tree. public: // method 1 bool Find(T& item); // method 2 CBinaryTreeNode * FindNode(const T &item, CBinaryTreeNode * &parent) const; // method 3 void Insert(const T& item); // method 4 CBinaryTreeNode * Delete(const T& item); };
Finding a Node and its Parent template CBinaryTreeNode * CBinarySearchTree ::FindNode(const T& item, CBinaryTreeNode * &parent) const { CBinaryTreeNode *current = m_Root; parent = NULL; while ( current != NULL ) { if ( item == current->GetData() ) { break; } else { parent = current; if ( item GetData() ) { current = current->GetLeftChild(); } else { current = current->GetRightChild(); } return current; }
Finding an Item in a BST Given a key K and a BST T with the root R –If T is empty, return false. –If R contains K, return R’s data and true. –If K is less than R’s key, search in the left sub- tree. –If K is greater than R’s key, search in the right sub-tree.
Finding an Item in a BST template bool CBinarySearchTree ::Find(T& item) { CBinaryTreeNode *parent; m_Current = FindNode(item, parent); if ( m_Current != NULL ) { item = m_Current->GetData(); return true; } else { return false; }
Inserting an Item Given a key K, and a BST T –See if the BST already contains an item under K. If yes, do nothing. –If no such element is found, insert K at the point where the search terminated.
Inserting an Item template void CBinarySearchTree ::Insert(const T& item) { CBinaryTreeNode *current = m_Root, *parent = NULL; if ( Find(item) == true ) return; while ( current != NULL ) { parent = current; if ( item GetData() ) current = current->GetLeftChild(); else current = current->GetRightChild(); } CBinaryTreeNode *addedNode = new CBinaryTreeNode (item); if ( parent == NULL ) m_Root = addedNode; else if ( item GetData() ) parent->SetLeftChild(addedNode); else parent->SetRightChild(addedNode); m_Size++; }