1 / 71

Nell Dale Chapter 9 Trees Plus Slides 2 – 18 are not mandatory

C++ Plus Data Structures. Nell Dale Chapter 9 Trees Plus Slides 2 – 18 are not mandatory. Slides 2 – 18 can be omitted A Binary Expression Tree is. A special kind of binary tree in which: 1. Each leaf node contains a single operand ,

fauna
Télécharger la présentation

Nell Dale Chapter 9 Trees Plus Slides 2 – 18 are not mandatory

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. C++ Plus Data Structures Nell Dale Chapter 9 Trees Plus Slides 2 – 18 are not mandatory expanded by J. Goetz

  2. Slides 2 – 18 can be omittedA Binary Expression Tree is . . . A special kind of binary tree in which: 1. Each leaf nodecontains a single operand, 2. Each nonleaf nodecontains asingle binary operator, and 3. The left and right subtrees of an operator node represent subexpressions that must be evaluated beforeapplying the operator at the root of the subtree. expanded by J. Goetz

  3. A Two-Level Binary Expression treePtr ‘-’ ‘8’ ‘5’ INORDER TRAVERSAL: 8 - 5 has value 3 PREORDER TRAVERSAL: - 8 5 POSTORDER TRAVERSAL:8 5 - expanded by J. Goetz

  4. Levels Indicate Precedence When a binary expression tree is used to represent an expression, the levels of the nodes in the tree indicate their relative precedence of evaluation. Operations at higher levels of the tree are evaluated laterthan those below them. The operation at the root is always the last operation performed. expanded by J. Goetz

  5. ‘*’ ‘3’ ‘+’ ‘2’ ‘4’ A Binary Expression Tree What value does it have? ( 4 + 2 ) * 3 = 18 expanded by J. Goetz

  6. ‘*’ ‘3’ ‘+’ ‘2’ ‘4’ A Binary Expression Tree What infix, prefix, postfix expressions does it represent? expanded by J. Goetz

  7. ‘*’ ‘3’ ‘+’ ‘2’ ‘4’ A Binary Expression Tree Infix: ( ( 4 + 2 ) * 3 ) Prefix: * + 4 2 3 Postfix: 4 2 + 3 * has operators in order used expanded by J. Goetz

  8. ‘/’ Inorder Traversal: (A + H) / (M - Y) Print second tree ‘-’ ‘+’ ‘A’ ‘H’ ‘M’ ‘Y’ Print left subtree first Print right subtree last expanded by J. Goetz

  9. ‘/’ Preorder Traversal: / + A H - M Y Print first tree ‘-’ ‘+’ ‘A’ ‘H’ ‘M’ ‘Y’ Print left subtree second Print right subtree last expanded by J. Goetz

  10. ‘/’ Postorder Traversal: A H + M Y - / Print last tree ‘-’ ‘+’ ‘A’ ‘H’ ‘M’ ‘Y’ Print left subtree first Print right subtree second expanded by J. Goetz

  11. ‘/’ ‘3’ ‘+’ ‘2’ ‘4’ Evaluate this binary expression tree ‘*’ ‘-’ ‘5’ ‘8’ What infix, prefix, postfix expressions does it represent? expanded by J. Goetz

  12. ‘*’ ‘/’ ‘-’ ‘8’ ‘5’ ‘3’ ‘+’ ‘2’ ‘4’ A binary expression tree Infix:( ( 8 - 5 ) * ( ( 4 + 2 ) / 3 ) ) Format: Eval(left subtree) BinOperator Eval(right subtree) Prefix:* - 8 5 / + 4 2 3 Format:BinOperator Eval(left subtree) Eval(right subtree) Postfix:8 5 - 4 2 + 3 / * Format: Eval(left subtree) Eval(right subtree) BinOperator has operators in order used expanded by J. Goetz

  13. OPERATOR‘+’ OPERAND7 .whichType .operation .whichType .operand InfoNode has 2 forms enum OpType { OPERATOR, OPERAND } ; struct InfoNode { OpType whichType; union// ANONYMOUS union { // set the type field accordingly to whichType char operation ; int operand ; } }; expanded by J. Goetz

  14. OPERAND7 .whichType .operand Each node contains two pointers struct TreeNode { InfoNode info ;// Data member TreeNode* left ;// Pointer to left child TreeNode* right ; // Pointer to right child }; NULL 6000 .left .info .right expanded by J. Goetz

  15. int Eval ( TreeNode* ptr ) // Pre: ptr is a pointer to a binary expression tree. // Post: Function value = the value of the expression represented // by the binary tree pointed to by ptr. { switch ( ptr->info.whichType ) // test the type field { case OPERAND : return ptr->info.operand ; // Base Case: value = operand case OPERATOR : switch ( tree->info.operation ) { // General Case: Infix: Eval(left subtree) BinOperator Eval(right subtree) case ‘+’ : return ( Eval ( ptr->left ) + Eval ( ptr->right ) ) ; case ‘-’ : return ( Eval ( ptr->left ) - Eval ( ptr->right ) ) ; case ‘*’ : return ( Eval ( ptr->left ) * Eval ( ptr->right ) ) ; case ‘/’ : return ( Eval ( ptr->left ) / Eval ( ptr->right ) ) ; } } } 15 expanded by J. Goetz

  16. ExprTree ‘*’ ~ExprTree ‘3’ ‘+’ Build Evaluate . . . ‘2’ ‘4’ class ExprTree private: root expanded by J. Goetz

  17. // buildTree3.cpp // Function BuildTree builds a binary expression tree // for the prefix basic format: // BinOperator Eval(left subtree) Eval(right subtree) // This version restricts operands to single digits // p.515 v. good diagram 2nd Edition void BuildTree(TreeNode * & tree) { using namespace std; enum MoveType {RIGHT, LEFT}; MoveType nextMove = LEFT; // first move TreeNode* newNode = new TreeNode; TreeNode* lastNode; // trailing node char symbol; StackType<TreeNode*> stack; cin >> symbol; // read root symbol // first symbol is an operator cout << "operator:: " << symbol << endl; newNode->info.whichType = OPERATOR; newNode->info.operation = symbol; tree = newNode; cin >> symbol; // read next symbol while (symbol != LAST_SYMBOL) // LAST_SYMBOL = ‘;’ in class // template StackType { lastNode = newNode; // lastNode is trailing node newNode = new TreeNode; if (!isalpha(symbol)) // fill a tree node info { cout << "operator:: " << symbol << endl; newNode->info.whichType = OPERATOR; newNode->info.operation = symbol; } else { cout << "operand: " << symbol << endl; newNode->info.whichType = OPERAND; newNode->info.operand = int(symbol - '0'); newNode->right = NULL; newNode->left = NULL; } switch (nextMove) { case LEFT : lastNode->left = newNode; stack.Push(lastNode); // forward break; case RIGHT : stack.Pop(lastNode); // backward lastNode->right = newNode; break; } // select next move if (newNode->info.whichType == OPERATOR) nextMove = LEFT; else nextMove = RIGHT; cin >> symbol; // read next symbol } } expanded by J. Goetz

  18. A full binary tree A full binary tree is a binary tree in which all the leaves are on the samelevel and every non leaf node has two children. SHAPE OF A FULL BINARY TREE expanded by J. Goetz

  19. A complete binary tree A complete binary tree is a binary tree that is either full or full through the next-to-last level, with the leaves on the last level as far to the left as possible. SHAPE OF A COMPLETE BINARY TREE expanded by J. Goetz

  20. Examples of Different Types of Binary Trees expanded by J. Goetz

  21. A binary tree • A binary tree can be stored in an array in such way that the relationships in the tree are not physically represented by link members. • But they are implicit in the algorithms that manipulate the tree stored in the array. • We store in such a way that the parent-child relationships is not lost. • We store the tree elements in the array, level by level, left-to-right. expanded by J. Goetz

  22. tree [ 0 ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] 70 60 12 40 30 8 70 0 12 2 60 1 40 3 30 4 8 5 And use the numbers as array indexes to store the tree tree.nodes expanded by J. Goetz

  23. Do you see the pattern? • For any node tree.nodes[index] • its left child is in • tree.nodes[index*2 + 1] • right child is in • tree.nodes[index*2 + 2] • its parent is in • tree.nodes[(index – 1)/2] • Note: tree.nodes[tree.numElements / 2] to tree.nodes[tree.numElements - 1] are leaf nodes expanded by J. Goetz

  24. A binary tree • The array-based representation is simple to implement for trees that are full or complete, because the elements occupy contiguous array slots. • If a tree is not full or complete we must store a dummy value in those positions in the array in order to maintain the proper parent-child relationship. . expanded by J. Goetz

  25. A Binary Search Tree Stored in an Array with Dummy Values expanded by J. Goetz

  26. How can you determine whether a parent tree.nodes[index] has a left child? Check the proper dummy value in tree.nodes[index * 2 + 1] expanded by J. Goetz

  27. What is a Heap? A heap is a binary tree that satisfies these special SHAPEand ORDERproperties: • The shape property: Its shape must be a completebinary tree. • The order property: For each node in the heap, the value stored in that node is greater than or equalto the value in each of its children. expanded by J. Goetz

  28. treePtr 50 C 30 20 A T 10 18 Are these both heaps? expanded by J. Goetz

  29. 70 Is this a heap? tree 12 60 40 30 8 10 expanded by J. Goetz

  30. 70 • Compare to the next slide: • The placement of the values differs • The shape is the same • The same root tree 40 60 12 30 8 expanded by J. Goetz

  31. 70 0 We can number the nodes left to right by level this way tree 12 2 60 1 40 3 30 4 8 5 expanded by J. Goetz

  32. tree [ 0 ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] 70 60 12 40 30 8 70 0 12 2 60 1 40 3 30 4 8 5 And use the numbers as array indexes to store the tree tree.nodes expanded by J. Goetz

  33. 70 • We want to remove the largest value from any subtree and • fill the hole with bottom rightmost element (replace 70 by 30) The shape property is OK but the replacement came from the buttom of the tree, where the smallest values are. The order is violated. So we need a basic heap operation to fix it: ReheapDown ( int root , int bottom ) ; tree 12 60 40 30 expanded by J. Goetz

  34. // HEAP SPECIFICATION // Assumes ItemType is either a built-in simple data type // or a class with overloaded realtional operators. template< class ItemType > struct HeapType // it is not a class, used for higher level classes {// they acted upon by other structures rather then being active void ReheapDown ( int root , int bottom ) ; // fix the order after removal void ReheapUp ( int root, int bottom ) ; // fix the order after adding ItemType* elements ; // ARRAY to be allocated dynamically int numElements ; // # of elements on the heap, alg doesn’t use it }; 34 expanded by J. Goetz

  35. ReheapDown // IMPLEMENTATION OF RECURSIVE HEAP MEMBER FUNCTIONS template< class ItemType > void HeapType<ItemType>::ReheapDown ( int root, int bottom ) // Pre: root is the index of the node that may violate the heap // order property // Post: Heap order property is restored between root and bottom // Move the element down from the root position until it ends up in a position where the order property is satisfied 35 expanded by J. Goetz

  36. void HeapType<ItemType>::ReheapDown ( int root, int bottom ) { // note: the current root is moving down, it used to remove an element from a heap int maxChild ; //it will store thecurrent rootwith max value int rightChild ; // index int leftChild ; // index leftChild = root * 2 + 1 ; // calculate the left child index if the parent index is known rightChild = root * 2 + 2 ; // calculate the right child index if the parent index is known if ( leftChild <= bottom ) // ReheapDown continued if it is not a leaf { // find thecurrent root if ( leftChild == bottom ) // leftChild reached bottom maxChild = leftChild ; // has only a left child because the tree is complete (not right child) else { // leftChild < bottom, so move down to the bigger node and set up maxChild if (elements [ leftChild ] <= elements [ rightChild ] ) maxChild = rightChild ; else maxChild = leftChild ; } if ( elements [ root ] < elements [ maxChild ] ) { // General Case: This shrinks the size of the tree to be processed Swap ( elements [ root ] , elements [ maxChild ] ) ; // swap the value in the current root with its larger child ReheapDown ( maxChild, bottom ) ; // repeat the process with the current root = maxChild } // Base Case: the heap order is already satisfied (intact) } // Base Case: leftChild > bottom, so it elements[root] is a leaf , no children for root } 36 expanded by J. Goetz

  37. 70 • We want to add an element to the heap and • The shape property tell us the tree must complete, so we put it in the next bottom rightmost place in the tree. (i.e. add 80 or 6) The shape property is OK but adding violates the order property. So we need a basic heap operation to fix it: ReheapUp ( int root , int bottom ) ; tree 12 60 40 30 8 expanded by J. Goetz

  38. // IMPLEMENTATION continued template< class ItemType > void HeapType<ItemType>::ReheapUp ( int root, int bottom ) // it used to add element to a heap // Pre: bottom is the index of the node that may violate the heap // order property. The order property is satisfied from root to // next-to-last node. // Post: Heap order property is restored between root and bottom // We need to float the N-th element up in tree until it is correct place. // Take a leaf node that violates the order property of heaps and moves up until // the correct position found // note: the current parent is moving up { int parent; // it will store thecurrent parentwith max value if ( bottom > root ) { parent = ( bottom - 1 ) / 2; // calculate thecurrent parentindex of bottom node if ( elements [ parent ] < elements [ bottom ] ) { Swap ( elements [ parent ], elements [ bottom ] ) ; ReheapUp ( root, parent ) ; // General Case: This shrinks the size of the tree to be processed } // Base Case: the heap order is already intact, elements [ parent] >= elements [ bottom ] } // Base Case: bottom < = root , so it elements[parent] is a root } 38 expanded by J. Goetz

  39. Priority Queue A priority queue is an ADT with the property that only the highest-priority element can be accessed at any time. It returns the item in the queue with the highest priority. expanded by J. Goetz

  40. ADT Priority Queue Operations Transformers • MakeEmpty • Enqueue • Dequeue Observers • IsEmpty • IsFull change state observe state 40 expanded by J. Goetz

  41. // CLASS PQTYPE DEFINITION AND MEMBER FUNCTIONS //-------------------------------------------------------- #include "ItemType.h" // for ItemType template<class ItemType> class PQType { public: PQType( int ); ~PQType ( ); void MakeEmpty( ); bool IsEmpty() const; bool IsFull( ) const; void Enqueue( ItemType item ); void Dequeue( ItemType& item ); private: int length; HeapType<ItemType> items; //struct type int maxItems; }; 41 expanded by J. Goetz

  42. PQType ~PQType Enqueue Dequeue . . . class PQType<char> Private Data: length 3 maxItems 10 Items (slide 34) .elements .numElements [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] ‘X’ ‘C’ ‘J’ expanded by J. Goetz

  43. Class PQType Function Definitions template<class ItemType> PQType<ItemType>::PQType(int max) { maxItems = max; items.elements = new ItemType[max]; length = 0; } template<class ItemType> void PQType<ItemType>::MakeEmpty() { length = 0; } template<class ItemType> PQType<ItemType>::~PQType() { delete [] items.elements; } expanded by J. Goetz

  44. Class PQType Function Definitions Dequeue Set item to root element from queue Move last leaf element into root position Decrement length items.ReheapDown(0, length-1) Enqueue Increment length Put newItem in next available position items.ReheapUp(0, length-1) expanded by J. Goetz

  45. Code for Dequeue class EmptyPQ() {}; template<class ItemType> void PQType<ItemType>::Dequeue(ItemType& item) // removes the element in the root node and replaces it with the bottom rightmost leaf node { if (length == 0) // empty? throw EmptyPQ(); else { item = items.elements[0]; // take the largest one // Move last leaf element into root position items.elements[0] = items.elements[length-1]; length--; items.ReheapDown(0, length-1); // fix an order property // complexity is 0(log2N) } } expanded by J. Goetz

  46. Code for Enqueue class FullPQ() {}; template<class ItemType> void PQType<ItemType>::Enqueue(ItemType newItem) // put a new element into the next free leaf node in the heap { if (length == maxItems) // full ? throw FullPQ(); else { length++; // Put newItem in next available (last) position items.elements[length-1] = newItem; items.ReheapUp(0, length-1); // fix an order property, // complexity is 0(log2N) } } expanded by J. Goetz

  47. Code for IsFull(), IsEmpty() template<class ItemType> bool PQType<ItemType>::IsFull() const // Post: Returns true if the queue is full; false, otherwise. { return length == maxItems; } template<class ItemType> bool PQType<ItemType>::IsEmpty() const // Post: Returns true if the queue is empty; false, otherwise. { return length == 0; } expanded by J. Goetz

  48. Implementation Level: Heap = best choice • There are many ways to implement apriority queue • An unsorted List- dequeuing would require searching through the entire list, it is 0(N) • An Array-Based Sorted List- Enqueuing is expensive 0(log2N) steps , dequeuing is an O(1) operation • A Reference-Based Sorted List- Enqueuing again is 0(N), dequeuing is O(1) for descending order, because first one • A Binary Search Tree-On average, 0(log2N) steps for both enqueue and dequeue by returning the rightmost tree element • AHeap- guarantees 0(log2N) steps, even in the worst case !!! • A complete tree is of minimum hight, at most [log2N] levels exist, so to fix the order property is needed 0(log2N) steps for ReheapUp() and ReheapDown() expanded by J. Goetz

  49. Enqueue Dequeue Heap O(log2N) O(log2N) Linked List O(N) O(N) Binary Search Tree Balanced O(log2N) O(log2N) Skewed O(N) O(N) Comparison of Priority Queue Implementations expanded by J. Goetz

  50. Definitions • Graph: A data structure that consists of a set of nodes and a set of edges that relate the nodes to each other • Vertex: A node in a graph • Edge (arc): A pair of vertices representing a connection between two nodes in a graph • Undirected graph: A graph in which the edges have no direction • Directed graph (digraph): A graph in which each edge is directed from one vertex to another (or the same) vertex expanded by J. Goetz

More Related