Intro to Data Structures Andy Wang Object Oriented Programming in C++ COP 3330
Abstract Data Types C++ offers other built-in ways to store data In addition to arrays Since C++ separates interface from implementation You can use built-in data structures without knowing how they are built Dynamic memory allocation is automatically handled Some common data structures include Stacks, queues, vectors, linked lists, trees, hash tables, sets, etc.
Stacks First In Last Out (FILO) Analogy Two primary operations Insertions and removals from “top” position only Analogy A stack of cafeteria trays New trays placed on top Trays picked up from the top Two primary operations push: adds an item onto the top of the stack pop: removes the top item from the stack Applications: function call stack, compilers, operating systems
Queues First In First Out (FIFO) Analogy Two primary operations Insertions at the “end” of the queue Removals from the “front” of the queue Analogy Waiting in line in a drive through First come, first serve Two primary operations enqueue: adds an item into the queue dequeue: removes an item from the queue Applications: scheduling, operating systems
Vector Stores items of the same type, similar to an array By encapsulating an array into a vector class, we can Use dynamic allocation Handle boundary issues of the array + Random access (quick locating of data if the index is known) - Inserts and deletes are typically slow, since they may require shifting many elements to consecutive array slots
Linked List Same type items linked together with pointers, lined up “in a row” Similar to an array, but arranged differently Made up of self-referential class A class embeds member data of the same class type Each list node class object contains a piece of data, and a pointer to the next node Nodes do not need to be consecutive Nodes allocated dynamically An alternative to array-based storage
Linked List + Inserts and deletes are fast No random access Only create a new node and change a few pointers No random access Possible to build indexing into a linked list Locating an element requires walking through the list Advantages of a linked list are generally disadvantages of an array (vector), and vice versa
Note Stacks and queues can be implemented with a vector or with a linked list Just restrict which end to insert and remove
Tree A hierarchical collection of items, linked together with pointers Made up of self-referential class Embedded with two or more pointers to objects of the same class Typical example: a binary tree Each binary tree node object contains a data element, and two pointers, each points to another node Useful for fast searching and sorting of data, assuming data items can be ordered Binary search: finds a path through the tree, starting at the “root”, and each chosen path (left or right) eliminates half of he stored values
Examples (Implemented as Class Templates) http://www.cs.fsu.edu/~myers/deitel5c++/ch21/ Fig 21_3-5: Linked List class Fig 21_13-14: Stack class, implemented with inheritance using the linked list class Fig 21_15: Stack class, implemented with composition, using the linked list class Stack contains a List object as member data Fig 21_16-17: Queue class, derived from List Fig 21_20-22: Tree class (binary)
Need to use a forward declaration. ListNode.h Need to use a forward declaration. Can’t just #include “List.h”, since it includes “ListNode.h” #ifndef _LISTNODE_H #define _LISTNODE_H template<class T> class List; template<class T> class ListNode { friend class List<T>; public: ListNode(const T &info) { data = info; nextPtr = 0 } T &GetData const { return data; } private: T data; ListNode<T> *nextPtr; }; #endif Allows class List<T> to access its private member data data nextPtr ListNode data nextPtr ListNode
List.h #ifndef _LIST_H #define _LIST_H #include “ListNode.h” #include <iostream> using namespace std; template<class T> class List { public: List() { firstPtr = lastPtr = 0; } ~List(); void InsertAtFront (const T &); void InsertAtBack (const T &); bool RemoveFromFront(T &); bool RemoveFromBack(T &); bool IsEmpty() const { return (firstPtr == 0); } bool Print() const; firstPtr lastPtr List
List.h private: ListNode<T> *firstPtr; ListNode<T> *lastPtr; };
List.h template<class T> void List<T>::InsertAtFront(const T &value) { ListNode<T> *newPtr = new ListNode<T>(value); if (IsEmpty()) { firstPtr = lastPtr = newPtr; } else { newPtr->nextPtr = firstPtr; firstPtr = newPtr; } newPtr value nextPtr ListNode
List.h template<class T> void List<T>::InsertAtFront(const T &value) { ListNode<T> *newPtr = new ListNode<T>(value); if (IsEmpty()) { firstPtr = lastPtr = newPtr; } else { newPtr->nextPtr = firstPtr; firstPtr = newPtr; } newPtr value nextPtr ListNode firstPtr lastPtr List
List.h template<class T> void List<T>::InsertAtFront(const T &value) { ListNode<T> *newPtr = new ListNode<T>(value); if (IsEmpty()) { firstPtr = lastPtr = newPtr; } else { newPtr->nextPtr = firstPtr; firstPtr = newPtr; } newPtr value nextPtr ListNode firstPtr lastPtr List
List.h template<class T> void List<T>::InsertAtFront(const T &value) { ListNode<T> *newPtr = new ListNode<T>(value); if (IsEmpty()) { firstPtr = lastPtr = newPtr; } else { newPtr->nextPtr = firstPtr; firstPtr = newPtr; } newPtr value nextPtr ListNode firstPtr lastPtr List value nextPtr ListNode
List.h template<class T> void List<T>::InsertAtFront(const T &value) { ListNode<T> *newPtr = new ListNode<T>(value); if (IsEmpty()) { firstPtr = lastPtr = newPtr; } else { newPtr->nextPtr = firstPtr; firstPtr = newPtr; } newPtr value nextPtr ListNode firstPtr lastPtr List value nextPtr ListNode
List.h template<class T> void List<T>::InsertAtFront(const T &value) { ListNode<T> *newPtr = new ListNode<T>(value); if (IsEmpty()) { firstPtr = lastPtr = newPtr; } else { newPtr->nextPtr = firstPtr; firstPtr = newPtr; } newPtr value nextPtr ListNode firstPtr lastPtr List value nextPtr ListNode
List.h template<class T> void List<T>::InsertAtBack(const T &value) { ListNode<T> *newPtr = new ListNode<T>(value); if (IsEmpty()) { firstPtr = lastPtr = newPtr; } else { lastPtr->nextPtr = newPtr; lastPtr = newPtr; } value nextPtr ListNode newPtr
List.h template<class T> void List<T>::InsertAtBack(const T &value) { ListNode<T> *newPtr = new ListNode<T>(value); if (IsEmpty()) { firstPtr = lastPtr = newPtr; } else { lastPtr->nextPtr = newPtr; lastPtr = newPtr; } firstPtr lastPtr List value nextPtr ListNode newPtr
List.h template<class T> void List<T>::InsertAtBack(const T &value) { ListNode<T> *newPtr = new ListNode<T>(value); if (IsEmpty()) { firstPtr = lastPtr = newPtr; } else { lastPtr->nextPtr = newPtr; lastPtr = newPtr; } firstPtr lastPtr List value nextPtr ListNode newPtr
List.h template<class T> void List<T>::InsertAtBack(const T &value) { ListNode<T> *newPtr = new ListNode<T>(value); if (IsEmpty()) { firstPtr = lastPtr = newPtr; } else { lastPtr->nextPtr = newPtr; lastPtr = newPtr; } value nextPtr ListNode firstPtr lastPtr List value nextPtr ListNode newPtr
List.h template<class T> void List<T>::InsertAtBack(const T &value) { ListNode<T> *newPtr = new ListNode<T>(value); if (IsEmpty()) { firstPtr = lastPtr = newPtr; } else { lastPtr->nextPtr = newPtr; lastPtr = newPtr; } value nextPtr ListNode firstPtr lastPtr List value nextPtr ListNode newPtr
List.h template<class T> void List<T>::InsertAtBack(const T &value) { ListNode<T> *newPtr = new ListNode<T>(value); if (IsEmpty()) { firstPtr = lastPtr = newPtr; } else { lastPtr->nextPtr = newPtr; lastPtr = newPtr; } value nextPtr ListNode firstPtr lastPtr List value nextPtr ListNode newPtr
List.h template<class T> bool List<T>::RemoveFromFront(T &value) { if (IsEmpty()) { return false; } else { ListNode<T> *tempPtr = firstPtr; if (firstPtr == lastPtr) { firstPtr = lastPtr = 0; firstPtr = firstPtr->nextPtr; } value = tempPtr->data; delete tempPtr; return true; firstPtr lastPtr List
List.h template<class T> bool List<T>::RemoveFromFront(T &value) { if (IsEmpty()) { return false; } else { ListNode<T> *tempPtr = firstPtr; if (firstPtr == lastPtr) { firstPtr = lastPtr = 0; firstPtr = firstPtr->nextPtr; } value = tempPtr->data; delete tempPtr; return true; tempPtr value nextPtr ListNode firstPtr lastPtr List
List.h template<class T> bool List<T>::RemoveFromFront(T &value) { if (IsEmpty()) { return false; } else { ListNode<T> *tempPtr = firstPtr; if (firstPtr == lastPtr) { firstPtr = lastPtr = 0; firstPtr = firstPtr->nextPtr; } value = tempPtr->data; delete tempPtr; return true; tempPtr value nextPtr ListNode firstPtr lastPtr List
List.h template<class T> bool List<T>::RemoveFromFront(T &value) { if (IsEmpty()) { return false; } else { ListNode<T> *tempPtr = firstPtr; if (firstPtr == lastPtr) { firstPtr = lastPtr = 0; firstPtr = firstPtr->nextPtr; } value = tempPtr->data; delete tempPtr; return true; tempPtr value nextPtr ListNode firstPtr lastPtr List
List.h template<class T> bool List<T>::RemoveFromFront(T &value) { if (IsEmpty()) { return false; } else { ListNode<T> *tempPtr = firstPtr; if (firstPtr == lastPtr) { firstPtr = lastPtr = 0; firstPtr = firstPtr->nextPtr; } value = tempPtr->data; delete tempPtr; return true; tempPtr value nextPtr ListNode firstPtr lastPtr List value nextPtr ListNode
List.h template<class T> bool List<T>::RemoveFromFront(T &value) { if (IsEmpty()) { return false; } else { ListNode<T> *tempPtr = firstPtr; if (firstPtr == lastPtr) { firstPtr = lastPtr = 0; firstPtr = firstPtr->nextPtr; } value = tempPtr->data; delete tempPtr; return true; tempPtr value nextPtr ListNode firstPtr lastPtr List value nextPtr ListNode
List.h template<class T> bool List<T>::RemoveFromFront(T &value) { if (IsEmpty()) { return false; } else { ListNode<T> *tempPtr = firstPtr; if (firstPtr == lastPtr) { firstPtr = lastPtr = 0; firstPtr = firstPtr->nextPtr; } value = tempPtr->data; delete tempPtr; return true; firstPtr lastPtr List value nextPtr ListNode
List.h template<class T> bool List<T>::RemoveFromBack(T &value) { if (IsEmpty()) { return false; } ListNode<T> *tempPtr = lastPtr; if (firstPtr == lastPtr) { firstPtr = lastPtr = 0; } else { ListNode<T> *currentPtr = firstPtr; while (currentPtr->nextPtr != lastPtr) currentPtr = currentPtr->nextPtr; lastPtr = currentPtr; currentPtr->nextPtr = 0; } value = tempPtr->data; delete tempPtr; return true;
List.h template<class T> bool List<T>::RemoveFromBack(T &value) { if (IsEmpty()) { return false; } ListNode<T> *tempPtr = lastPtr; if (firstPtr == lastPtr) { firstPtr = lastPtr = 0; } else { ListNode<T> *currentPtr = firstPtr; while (currentPtr->nextPtr != lastPtr) currentPtr = currentPtr->nextPtr; lastPtr = currentPtr; currentPtr->nextPtr = 0; } value = tempPtr->data; delete tempPtr; return true; firstPtr lastPtr List
List.h template<class T> bool List<T>::RemoveFromBack(T &value) { if (IsEmpty()) { return false; } ListNode<T> *tempPtr = lastPtr; if (firstPtr == lastPtr) { firstPtr = lastPtr = 0; } else { ListNode<T> *currentPtr = firstPtr; while (currentPtr->nextPtr != lastPtr) currentPtr = currentPtr->nextPtr; lastPtr = currentPtr; currentPtr->nextPtr = 0; } value = tempPtr->data; delete tempPtr; return true; firstPtr lastPtr List value nextPtr ListNode tempPtr
List.h template<class T> bool List<T>::RemoveFromBack(T &value) { if (IsEmpty()) { return false; } ListNode<T> *tempPtr = lastPtr; if (firstPtr == lastPtr) { firstPtr = lastPtr = 0; } else { ListNode<T> *currentPtr = firstPtr; while (currentPtr->nextPtr != lastPtr) currentPtr = currentPtr->nextPtr; lastPtr = currentPtr; currentPtr->nextPtr = 0; } value = tempPtr->data; delete tempPtr; return true; firstPtr lastPtr List value nextPtr ListNode tempPtr
List.h template<class T> bool List<T>::RemoveFromBack(T &value) { if (IsEmpty()) { return false; } ListNode<T> *tempPtr = lastPtr; if (firstPtr == lastPtr) { firstPtr = lastPtr = 0; } else { ListNode<T> *currentPtr = firstPtr; while (currentPtr->nextPtr != lastPtr) currentPtr = currentPtr->nextPtr; lastPtr = currentPtr; currentPtr->nextPtr = 0; } value = tempPtr->data; delete tempPtr; return true; firstPtr lastPtr List value nextPtr ListNode tempPtr
List.h currentPtr template<class T> bool List<T>::RemoveFromBack(T &value) { if (IsEmpty()) { return false; } ListNode<T> *tempPtr = lastPtr; if (firstPtr == lastPtr) { firstPtr = lastPtr = 0; } else { ListNode<T> *currentPtr = firstPtr; while (currentPtr->nextPtr != lastPtr) currentPtr = currentPtr->nextPtr; lastPtr = currentPtr; currentPtr->nextPtr = 0; } value = tempPtr->data; delete tempPtr; return true; value nextPtr ListNode firstPtr lastPtr List value nextPtr ListNode tempPtr
List.h currentPtr template<class T> bool List<T>::RemoveFromBack(T &value) { if (IsEmpty()) { return false; } ListNode<T> *tempPtr = lastPtr; if (firstPtr == lastPtr) { firstPtr = lastPtr = 0; } else { ListNode<T> *currentPtr = firstPtr; while (currentPtr->nextPtr != lastPtr) currentPtr = currentPtr->nextPtr; lastPtr = currentPtr; currentPtr->nextPtr = 0; } value = tempPtr->data; delete tempPtr; return true; value nextPtr ListNode firstPtr lastPtr List value nextPtr ListNode tempPtr
List.h currentPtr template<class T> bool List<T>::RemoveFromBack(T &value) { if (IsEmpty()) { return false; } ListNode<T> *tempPtr = lastPtr; if (firstPtr == lastPtr) { firstPtr = lastPtr = 0; } else { ListNode<T> *currentPtr = firstPtr; while (currentPtr->nextPtr != lastPtr) currentPtr = currentPtr->nextPtr; lastPtr = currentPtr; currentPtr->nextPtr = 0; } value = tempPtr->data; delete tempPtr; return true; value nextPtr ListNode firstPtr lastPtr List value nextPtr ListNode tempPtr
List.h currentPtr template<class T> bool List<T>::RemoveFromBack(T &value) { if (IsEmpty()) { return false; } ListNode<T> *tempPtr = lastPtr; if (firstPtr == lastPtr) { firstPtr = lastPtr = 0; } else { ListNode<T> *currentPtr = firstPtr; while (currentPtr->nextPtr != lastPtr) currentPtr = currentPtr->nextPtr; lastPtr = currentPtr; currentPtr->nextPtr = 0; } value = tempPtr->data; delete tempPtr; return true; value nextPtr ListNode firstPtr lastPtr List value nextPtr ListNode tempPtr
List.h currentPtr template<class T> bool List<T>::RemoveFromBack(T &value) { if (IsEmpty()) { return false; } ListNode<T> *tempPtr = lastPtr; if (firstPtr == lastPtr) { firstPtr = lastPtr = 0; } else { ListNode<T> *currentPtr = firstPtr; while (currentPtr->nextPtr != lastPtr) currentPtr = currentPtr->nextPtr; lastPtr = currentPtr; currentPtr->nextPtr = 0; } value = tempPtr->data; delete tempPtr; return true; value nextPtr ListNode firstPtr lastPtr List
List.h template<class T> void List<T>::Print() const { if (IsEmpty()) { cout << "The list is empty\n\n"; return; } cout << "The list is: "; ListNode<T> *currentPtr = firstPtr; for (currentPtr = firstPtr; currentPtr; currentPtr = currentPtr->nextPtr) cout << currentPtr->data << ' '; cout << "\n\n"; #endif
List.h template<class T> void List<T>::Print() const { if (IsEmpty()) { cout << "The list is empty\n\n"; return; } cout << "The list is: "; ListNode<T> *currentPtr = firstPtr; for (currentPtr = firstPtr; currentPtr; currentPtr = currentPtr->nextPtr) cout << currentPtr->data << ' '; cout << "\n\n"; #endif
Fig21_05.cpp #include <iostream> #include <string> using namespace std; #include "List.h" void instructions() { cout << "Enter one of the following:\n" << " 1 to insert at beginning of list\n" << " 2 to insert at end of list\n" << " 3 to delete from beginning of list\n" << " 4 to delete from end of list\n" << " 5 to end list processing\n"; }
Fig21_05.cpp template<class T> void TestList(List<T> &l, const string &typeName) { cout << "Test a List of " << typeName << " values\n"; instructions(); int choice; T value; do { cout << "? "; cin >> choice; switch(choice) { case 1: cout << "Enter " << typeName << ": "; cin >> value; l.InsertAtFront(value); l.Print(); break;
Fig21_05.cpp case 2: cout << "Enter " << typeName << ": "; cin >> value; l.InsertAtBack(value); l.Print(); break; case 3: if (l.RemoveFromFront(value)) cout << value << " removed from list\n"; l.Print(); break; case 4: if (l.RemoveFromBack(value)) } } while (choice != 5);
Fig21_05.cpp int main() { List<int> integerList; TestList(integerList, "integer"); List<double> doubleList; TestList(doubleList, "double"); return 0; }
Stack.h (Private Inheritance) Everything inherited becomes private #ifndef _STACK_H #define _STACK_H #include "List.h" template<class T> class Stack : private List<T> { public: void Push(const T &data) { InsertAtFront(data); } bool Pop(T &data) { return RemoveFromFront(data); } bool IsStackEmpty() const { return this->IsEmpty(); } void PrintStack() const { this->Print(); } }; #endif
Stack.h (Composition) #ifndef _STACK_H #define _STACK_H #include "List.h“ template<class T> class Stack { public: void Push(const T &data) { stackList.InsertAtFront(data); } bool Pop(T &data) { return stackList.RemoveFromFront(data); } bool IsStackEmpty() const { return stackList.IsEmpty(); } void PrintStack() const { stackList.Print(); } private: List<T> stackList; }; #endif
Fig21_14.cpp #include <iostream> using namespace std; #include "Stack.h" int main() { Stack<int> intStack; cout << "processing an integer Stack" << endl; for (int i = 0; i < 3; i++) { intStack.Push(i); intStack.PrintStack(); } int popInteger; while (!intStack.IsStackEmpty()) { intStack.Pop(popInteger); cout << popInteger << " popped from stack" << endl; intStack.PrintStack();
Fig21_14.cpp Stack <double> doubleStack; double value = 1.1; cout << "procesing a double Stack" << endl; for (int j = 0; j < 3; j++, value += 1.1) { doubleStack.Push(value); doubleStack.PrintStack(); } double popDouble; while (!doubleStack.IsStackEmpty()) { doubleStack.Pop(popDouble); cout << popDouble << " popped from stack" << endl; return 0;
Queue.h #ifndef _QUEUE_H #define _QUEUE_H #include "List.h" template<class T> class Queue : private List<T> { public: void Enqueue(const T &data) { InsertAtBack(data); } bool Dequeue(T &data) { return RemoveFromFront(data); } bool IsQueueEmpty() const { return this->IsEmpty(); } void PrintQueue() const { this->Print(); } }; #endif
Fig21_17.cpp #include <iostream> using namespace std; #include “Queue.h" int main() { Queue<int> intQueue; cout << "processing an integer Queue" << endl; for (int i = 0; i < 3; i++) { intQueue.Enqueue(i); intQueue.PrintQueue(); } int dequeueInteger; while (!intQueue.IsQueueEmpty()) { intQueue.Dequeue(dequeueInteger); cout << dequeueInteger << " dequeued" << endl; intQueue.PrintQueue();
Fig21_14.cpp Queue <double> doubleQueue; double value = 1.1; cout << "procesing a double Queue" << endl; for (int j = 0; j < 3; j++, value += 1.1) { doubleQueue.Enqueue(value); doubleQueue.PrintQueue(); } double dequeueDouble; while (!doubleQueue.IsQueueEmpty()) { doubleQueue.Dequeue(dequeueDouble); cout << dequeueDouble << " dequeued" << endl; return 0;
Binary Tree leftPtr->data < data < rightPtr->data leftPtr
In Order Traversal leftPtr->data, data, rightPtr->data: 1, 2, 3, 4, 5 leftPtr rightPtr data = 4 leftPtr rightPtr data = 2 leftPtr rightPtr data = 5 leftPtr rightPtr data = 1 leftPtr rightPtr data = 3
Pre Order Traversal data, leftPtr->data, rightPtr->data: 4, 2, 1, 3, 5 leftPtr rightPtr data = 4 leftPtr rightPtr data = 2 leftPtr rightPtr data = 5 leftPtr rightPtr data = 1 leftPtr rightPtr data = 3
Post Order Traversal leftPtr->data, rightPtr->data, data: 1, 3, 2, 5, 4 leftPtr rightPtr data = 4 leftPtr rightPtr data = 2 leftPtr rightPtr data = 5 leftPtr rightPtr data = 1 leftPtr rightPtr data = 3
TreeNode.h #ifndef _TREENODE_H #define _TREENODE_H template<class T> class Tree; template<class T> class TreeNode { friend class Tree<T>; public: TreeNode(const T &d) : leftPtr(0), data(d), rightPtr(0) {} T GetData() const { return data; } private: TreeNode<T> *leftPtr; T data; TreeNode<T> *rightPtr; }; #endif
Tree.h #ifndef _TREE_H #define _TREE_H #include <iostream> #include <new> #include "TreeNode.h" using namespace std; template<class T> class Tree { public: Tree() { rootPtr = 0; } void InsertNode(const T &); void PreOrderTraversal() const; void InOrderTraversal() const; void PostOrderTraversal() const;
Tree.h private: TreeNode<T> *rootPtr; void PreOrderHelper(TreeNode<T> *) const; void InOrderHelper(TreeNode<T> *) const; void PostOrderHelper(TreeNode<T> *) const; };
Tree.h template<class T> void Tree<T>::InsertNode(const T &data) { if (!rootPtr) { rootPtr = new TreeNode<T>(data); return; } …
Tree.h TreeNode<T> *tempPtr = rootPtr; while (tempPtr) { if (data < tempPtr->data) { if (!tempPtr->leftPtr) { tempPtr->leftPtr = new TreeNode<T>(data); break; } else tempPtr = tempPtr->leftPtr; } else if (data > tempPtr->data) { if (!tempPtr->rightPtr) { tempPtr->rightPtr = new TreeNode<T>(data); } else tempPtr = tempPtr->rightPtr; } else break; }
InsertNode(4) rootPtr
rootPtr == NULL rootPtr
rootPtr = new TreeNode<T>(4) leftPtr rightPtr data = 4
InsertNode(2) rootPtr leftPtr rightPtr data = 4 tempPtr
2 < 4 && leftPtr == NULL rootPtr leftPtr rightPtr data = 4 tempPtr
tempPtr->leftPtr = new… rootPtr leftPtr rightPtr data = 4 tempPtr leftPtr rightPtr data = 2
InsertNode(1) rootPtr leftPtr rightPtr data = 4 tempPtr leftPtr
1 < 4 && tempPtr->leftPtr rootPtr leftPtr rightPtr data = 4 tempPtr leftPtr rightPtr data = 2
tempPtr = tempPtr->leftPtr rootPtr leftPtr rightPtr data = 4 tempPtr leftPtr rightPtr data = 2
1 < 2 && leftPtr == NULL rootPtr leftPtr rightPtr data = 4 tempPtr
tempPtr->leftPtr = new… rootPtr leftPtr rightPtr data = 4 tempPtr leftPtr rightPtr data = 2 leftPtr rightPtr data = 1
InsertNode(3) rootPtr leftPtr rightPtr data = 4 tempPtr leftPtr
3 < 4 && tempPtr->leftPtr rootPtr leftPtr rightPtr data = 4 tempPtr leftPtr rightPtr data = 2 leftPtr rightPtr data = 1
tempPtr = tempPtr->leftPtr rootPtr leftPtr rightPtr data = 4 tempPtr leftPtr rightPtr data = 2 leftPtr rightPtr data = 1
3 > 2 && !tempPtr->rightPtr rootPtr leftPtr rightPtr data = 4 tempPtr leftPtr rightPtr data = 2 leftPtr rightPtr data = 1
tempPtr->rightPtr = new… rootPtr leftPtr rightPtr data = 4 tempPtr leftPtr rightPtr data = 2 leftPtr rightPtr data = 1 leftPtr rightPtr data = 3
InsertNode(5) rootPtr leftPtr rightPtr data = 4 tempPtr leftPtr
5 > 4 && !tempPtr->rightPtr rootPtr leftPtr rightPtr data = 4 tempPtr leftPtr rightPtr data = 2 leftPtr rightPtr data = 1 leftPtr rightPtr data = 3
tempPtr->rightPtr = new… rootPtr leftPtr rightPtr data = 4 tempPtr leftPtr rightPtr data = 2 leftPtr rightPtr data = 5 leftPtr rightPtr data = 1 leftPtr rightPtr data = 3
Tree.h template<class T> void Tree<T>::PreOrderTraversal() const { PreOrderHelper(rootPtr); } void Tree<T>::PreOrderHelper(TreeNode<T> *ptr) const { if (ptr) { cout << ptr->data << ' '; PreOrderHelper(ptr->leftPtr); PreOrderHelper(ptr->rightPtr);
Tree.h template<class T> void Tree<T>::InOrderTraversal() const { InOrderHelper(rootPtr); } void Tree<T>::InOrderHelper(TreeNode<T> *ptr) const { if (ptr) { InOrderHelper(ptr->leftPtr); cout << ptr->data << ' '; InOrderHelper(ptr->rightPtr);
Tree.h template<class T> void Tree<T>::PostOrderTraversal() const { PostOrderHelper(rootPtr); } void Tree<T>::PostOrderHelper(TreeNode<T> *ptr) const { if (ptr) { PostOrderHelper(ptr->leftPtr); PostOrderHelper(ptr->rightPtr); cout << ptr->data << ' ';
Fig21_22.cpp #include <iostream> #include <iomanip> #include "Tree.h" using namespace std; int main() { Tree<int> intTree; int intValue; cout << "Enter 10 integer values: \n"; for (int i = 0; i < 10; i++) { cin >> intValue; intTree.InsertNode(intValue); }
Fig21_22.cpp cout << "\nPreorder traversal\n"; intTree.PreOrderTraversal(); cout << "\nInorder traversal\n"; intTree.InOrderTraversal(); cout << "\nPostorder traversal\n"; intTree.PostOrderTraversal();
Fig21_22.cpp Tree<double> doubleTree; double doubleValue; cout << fixed << setprecision(1) << “\n\n\nEnter 10 double values:\n"; for (int j = 0; j < 10; j++) { cin >> doubleValue; doubleTree.InsertNode(doubleValue); } cout << "\nPreorder traversal\n"; doubleTree.PreOrderTraversal(); cout << "\nInorder traversal\n"; doubleTree.InOrderTraversal(); cout << "\nPostorder traversal\n"; doubleTree.PostOrderTraversal(); return 0;