1 / 61

Trees & More Tables

Trees & More Tables. (Walls & Mirrors - Chapter 10 & Beginning of 11). Overview. Terminology Binary Trees Pointer-Based Representation of a Binary Tree Array-Based Representation of a Binary Tree Traversing a Binary Tree Binary Search Tree Implementation of a Table Treesort. Terminology.

patricia
Télécharger la présentation

Trees & More Tables

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. Trees & More Tables (Walls & Mirrors - Chapter 10 & Beginning of 11)

  2. Overview • Terminology • Binary Trees • Pointer-Based Representation of a Binary Tree • Array-Based Representation of a Binary Tree • Traversing a Binary Tree • Binary Search Tree Implementation of a Table • Treesort

  3. Terminology • A tree is a collection of nodes and directed edges, satisfying the following properties: • There is one specially designated node called the root, which has no edges pointing to it. • Every node except the root has exactly one edge pointing to it. • There is a unique path (of nodes and edges) from the root to each node.

  4. Trees: Not Trees: root edge node Graphical Representation • Trees, as defined on the preceding slide, are typically drawn with circles (or rectangles) representing the nodes and arrows representing the edges. • The root is typically placed at the top of the diagram, with the rest of the tree below it.

  5. Terminology (Cont’d.) • If an edge goes from node a to node b, then a is called the parent of b, and b is called a child of a. • Children of the same parent are called siblings. • If there is a path from a to b, then a is called an ancestor of b, and b is called a descendent of a. • A node with all of its descendants is called a subtree. • If a node has no children, then it is called a leaf of the tree. • If a node has no parent (there will be exactly one of these), then it is the root of the tree.

  6. A B C F D E G H I J K Terminology: Example • A is the root • D, E, G, H, J & K are leaves • B is the parent of D, E & F • D, E & F are siblings and children of B • I, J & K are descendants of B • A & B are ancestors of I subtree

  7. (These two binary trees are distinct.) Binary Trees • Intuitively, a binary tree is LIKE a tree in which each node has no more than two children. • Formally, a binary tree is a set T of nodes such that either: • T is empty, or • T consists of a single node, r, called the root, and two (non-overlapping) binary trees, called the left and rightsubtrees of r. • UNLIKE trees, binary trees may be empty, and they distinguish between left and rightsubtrees.

  8. 21 John 3 34 Brenda Peter 55 2 8 Amy Mary Tom 5 13 Binary Search Trees • A binary search tree is a binary tree in which each node, n, has a value satisfying the following properties: • n’s value is > all values in its left subtree, TL, • n’s value is < all values in its right subtree, TR, and • TLand TRare both binary search trees.

  9. Terminology (Cont’d.) • Intuitively, the level of a node is the number of nodes on a path from the root to the node. • Formally, level of node, n: • If n is the root of a tree, then it is at level 1. • Otherwise, its level is 1 greater than the level of its parent. • Height of binary tree, T: • If T is empty, its height is 0. • Otherwise, its height is the maximum level of its nodes, or, equivalently, 1 greater than the height of the root’s taller subtree. Namely, height(T) = 1 + max { height( TL ), height(TR ) }

  10. Terminology (Cont’d.) • Intuitively, a binary tree is full if it has no missing nodes. • Formally, a binary tree of height h is fullif • It is empty (h = 0). • Otherwise, the root’s subtrees are full binary trees of height h – 1. • If not empty, each node has2 children, except the nodes at level h which have no children. • Alternatively, the binary tree has all of its leaves at level h.

  11. Terminology (Cont’d.) • Intuitively, a binary tree of height h is complete if it is full down to level h – 1, and level h is filled from left to right. • Formally, a binary tree of height h is complete if • All nodes at level h – 2 and above have 2 children each, • If a node at level h – 1 has children, all nodes to its left at the same level have 2 children each, and • If a node at level h – 1 has 1 child, it is a left child.

  12. Terminology (Cont’d.) • A binary tree is balanced if the difference in height between any node’s left and right subtree is  1. • Note that: • A full binary tree is also complete. • A complete binary tree is not always full. • Full and complete binary trees are also balanced. • Balanced binary trees are not always full or complete.

  13. Binary Tree: Pointer-Based Representation struct TreeNode; // Binary Tree nodes are struct’s typedef string TreeItemType; // items in TreeNodes are string’s class BinaryTree { public: // declarations of public member functions private: TreeNode *root; // pointer to root of Binary Tree }; struct TreeNode // node in a Binary Tree: { // place in Implementation file TreeItemType item; TreeNode *leftChild; // pointer to TreeNode’s left child TreeNode *rightChild; // pointer to TreeNode’s right child };

  14. Binary Tree: Array-Based Representation Basic Idea: • Instead of using pointers to the left and right child of a node, use indices into the array of nodes representing the binary tree. • Also, use variable free as an index to the first position in the array that is available for a new entry. Use either the left or right child indices to indicate additional, available positions. • Together, the list of available positions in the array is called the free list.

  15. root 0 free 6 Nancy Ellen Alan Tom Jane Bob Binary Tree: Array-Based Representation

  16. root 0 free 7 Nancy Mary Ellen Alan Tom Jane Bob Binary Tree: Array-Based Representation • Mary Added under Nancy.

  17. root 0 free 4 Nancy Mary Alan Tom Jane Bob Binary Tree: Array-Based Representation • Ellen deleted.

  18. Binary Tree: Array-Based Representation const int MaxNodes = 100; // maximum size of a Binary Tree typedef string TreeItemType; // items in TreeNodes are string’s struct TreeNode // node in a Binary Tree { TreeItemType item; int leftChild; // index of TreeNode’s left child int rightChild; // index of TreeNode’s right child }; class BinaryTree { public: // declarations of public member functions private: TreeNode node[MaxNodes]; int root; // index of root of Binary Tree int free; // index of free list, linked by rightChild };

  19. Traversing a Binary Tree • Preorder • Inorder • Postorder

  20. Preorder Traversal of a Binary Tree Basic Idea: 1) Visit the root. 2) Recursively invoke preorder on the left subtree. 3) Recursively invoke preorder on the right subtree.

  21. 1 7 2 3 4 5 6 60 40 10 70 20 30 50 Preorder Traversal of a Binary Tree Preorder Result: 60, 20, 10, 40, 30, 50, 70

  22. Inorder Traversal of a Binary Tree Basic Idea: 1) Recursively invoke inorder on the left subtree. 2) Visit the root. 3) Recursively invoke inorder on the right subtree.

  23. 6 7 2 1 4 3 5 60 40 10 70 20 30 50 Inorder Traversal of a Binary Tree Inorder Result: 10, 20, 30, 40, 50, 60, 70

  24. Postorder Traversal of a Binary Tree Basic Idea: 1) Recursively invoke postorder on the left subtree. 2) Recursively invoke postorder on the right subtree. 3) Visit the root.

  25. 7 6 5 1 4 2 3 60 40 10 70 20 30 50 Postorder Traversal of a Binary Tree Postorder Result: 10, 30, 50, 40, 20, 70, 60

  26. Pointer-Based, Preorder Traversal in C++ // FunctionTypeis a pointer to a function with argument // (TreeItemType &) that returns void. typedef void (*FunctionType) (TreeItemType &treeItem); // Public member function void BinaryTree::preorderTraverse( FunctionType visit ) { preorder( root, visit ); }

  27. Pointer-Based, Preorder Traversal in C++ // Private member function void BinaryTree::preorder( TreeNode *treePtr, FunctionType visit ) { if( treePtr != NULL ) { visit( treePtr -> item ); preorder( treePtr -> leftChild, visit ); preorder( treePtr -> rightChild, visit ); } }

  28. Pointer-Based, Preorder Traversal in C++ Suppose that we define the function void printItem( TreeItemType &treeItem ) { cout << treeItem << endl; } Then, // create myTree BinaryTree myTree; // load data into myTree . . . // print TreeItems encountered in preorder traversal of myTree myTree.preorderTraverse( &printItem );

  29. Pointer-Based,Inorder & Postorder Traversal The functions for Inorder and Postorder traversal of a binary tree are very similar to the function for Preorder traversal, and are left as an exercise.

  30. Nonrecursive Traversal of a Binary Tree Basic Idea for a Nonrecursive, Inorder Traversal: 1) Push a pointer to the root of the binary tree onto a stack. 2) Follow leftChild pointers, pushing each one onto the stack, until a NULLleftChild pointer is found. 3) Process (visit) the item in this node. 4) Get the node’s rightChild pointer: • If it is notNULL, then push it onto the stack, and return to step 2 with the leftChild pointer of this rightChild. • If it is NULL, then pop a node pointer from the stack, and return to step 3. If the stack is empty (so nothing could be popped), then stop — the traversal is done.

  31. Nonrecursive Traversal of a Binary Tree • The logic for a nonrecursive, preorder or postorder traversal is similar to what was presented on the previous slide for an inorder traversal. • ~14 lines of code (see chapter 10 of Walls & Mirrors) plus the code for manipulating a stack are required to implement a nonrecursive traversal. Compare this with the 5 lines of code that were required for our recursive solutions. • This example illustrates how recursion can sometimes be used to produce a clear and concise implementation.

  32. Binary Search Tree Implementationof a Table Recall that the supported operations for an ADT Table include: • Create an empty table • Destroy a table • Determine whether a table is empty • Determine the number of items in a table • Insert a new item into a table • Delete the item with a given search key from a table • Retrieve the item with a given search key from a table • Traverse the items in a table in sorted, search-key order

  33. Table: Binary Search Tree Implementation typedef string KeyType; // Table search-keys are strings struct dataItem // all data for an item is put into { KeyType key; // one struct for convenience // other data members are included here }; typedef dataItem TableItemType; // items in Table are dataItems // returns tableItem’s searchKey KeyType getKey( const TableItemType &tableItem ) { return( tableItem.key ); } // FunctionType is a pointer to a function with argument // (TableItemType &) that returns void, used by Table traverse( ) typedef void (*FunctionType) (TableItemType &tableItem);

  34. Table: Binary Search Tree Implementation typedef TableItemType TreeItemType; // TableItems are stored struct TreeNode; // in TreeNodes class Table { public: // declarations of public member functions private: TreeNode *root; // root of Binary Search Tree int size; // number of items in Table }; struct TreeNode // node in a Binary Search Tree: { // place in Implementation file TreeItemType item; TreeNode *leftChild; // pointer to TreeNode’s left child TreeNode *rightChild; // pointer to TreeNode’s right child };

  35. Table: Binary Search Tree Implementation An alternative (and perhaps, better) implementation of a Table as a Binary Search Tree would define struct dataItem { KeyType key; // other data members are included here }; and struct TreeNode { TreeItemType item; TreeNode *leftChild; TreeNode *rightChild; }; as Classes, with constructors to set the key for a dataItem and to initialize leftChild and rightChild to NULL. getKey( ) would become a public member function, providing access to key. (See chapter 10 of Walls & Mirrors for details.)

  36. Table: Public Member Function Definitions // default constructor, which creates a new empty Table Table::Table( ) : root( NULL ), size( 0 ) { } // copy constructor, which copies origTable to a new Table Table::Table( const Table &origTable ) { copyTree( origTable.root, root ); size = origTable.size; } // destructor, which destroys a Table Table::~Table( ) { destroyTree( root ); }

  37. Table: Private Member Function Definition // copies tree rooted at origTreePtr to a new tree rooted at newTreePtr void Table::copyTree( TreeNode *origTreePtr, TreeNode *&newTreePtr ) const { if( origTreePtr != NULL ) // copy nodes using preorder traversal { newTreePtr = new TreeNode; assert( newTreePtr != NULL ); newTreePtr -> item = origTreePtr -> item; copyTree( origTreePtr -> leftChild, newTreePtr -> leftChild ); copyTree( origTreePtr -> rightChild, newTreePtr -> rightChild ); } else newTreePtr = NULL; }

  38. Table: Private Member Function Definition // destroys tree rooted at treePtr void Table::destroyTree( TreeNode *&treePtr ) { if( treePtr != NULL ) { // delete nodes using postorder traversal destroyTree( treePtr -> leftChild ); destroyTree( treePtr -> rightChild ); delete treePtr; treePtr = NULL; } }

  39. Table: Public Member Function Definitions // returns true if the Table is empty, otherwise returns false bool Table::isEmpty( ) const { return size = = 0; } // returns the number of items in the Table int Table::length( ) const { return size; }

  40. Table: Public Member Function Definitions // inserts newItem into a Table in sorted order bool Table::insert( TableItemType &newItem ) { if( treeInsertItem( root, newItem ) ) { size++; return true; } return false; } // removes item with the given searchKey from a Table bool Table::remove( KeyType searchKey ) { if( treeDeleteItem( root, searchKey ) ) { size – –; return true; } return false; }

  41. Table: Public Member Function Definitions // retrieves a copy of item with the given searchKey from a Table bool Table::retrieve( KeyType searchKey, TableItemType &tableItem ) const { return treeRetrieveItem( root, searchKey, tableItem ); }

  42. Table: Private Member Function Definition // inserts newItem into a Binary Search Tree rooted at treePtr bool Table::treeInsertItem( TreeNode *&treePtr, const TreeItemType &newItem ) { if( treePtr = = NULL ) { treePtr = new TreeNode; assert( treePtr != NULL ); treePtr -> item = newItem; treePtr -> leftChild = treePtr -> rightChild = NULL; return true; } if( getKey( newItem ) = = getKey( treePtr -> item ) ) return false; if( getKey( newItem ) < getKey( treePtr -> item ) ) return treeInsertItem( treePtr -> leftChild, newItem ); else return treeInsertItem( treePtr -> rightChild, newItem ); }

  43. Table: Private Member Function Definition // retrieves a copy of item with the given searchKey from a Binary // Search Tree rooted at treePtr bool Table::treeRetrieveItem( TreeNode *treePtr, KeyType searchKey, TreeItemType &treeItem ) const { if( treePtr = = NULL ) return false; KeyType itemKey = getKey( treePtr -> item ); if( searchKey = = itemKey ) { treeItem = treePtr -> item; return true; } if( searchKey < itemKey ) return treeRetrieveItem( treePtr -> leftChild, searchKey, treeItem ); else return treeRetrieveItem( treePtr -> rightChild, searchKey, treeItem ); }

  44. Table: Private Member Function Definition // deletes item with the given searchKey from a Binary Search Tree // rooted at treePtr bool Table::treeDeleteItem( TreeNode *&treePtr, KeyType searchKey ) { if( treePtr = = NULL ) return false; KeyType itemKey = getKey( treePtr -> item ); if( searchKey = = itemKey ) { treeDeleteNode( treePtr ); return true; } if( searchKey < itemKey ) return treeDeleteItem( treePtr -> leftChild, searchKey ); else return treeDeleteItem( treePtr -> rightChild, searchKey ); }

  45. Delete Node at treePtr from a Tree There are 4 cases: 1) treePtr points to a leaf 2) treePtr points to a node with no leftChild 3) treePtr points to a node with no rightChild 4) treePtr points to a node with both leftChild and rightChild

  46. Table: Private Member Function Definition // delete node at treePtr from a tree void Table::treeDeleteNode( TreeNode *&treePtr ) { if( treePtr -> leftChild = = NULL && treePtr -> rightChild = = NULL ) { /* delete leaf pointed to by treePtr */ } else if( treePtr -> leftChild = = NULL ) { /* delete node at treePtr, making treePtr point to rightChild */ } else if( treePtr -> rightChild = = NULL ) { /* delete node at treePtr, making treePtr point to leftChild */ } else { /* copy item from leftmost descendant of rightChild */ /* to node at treePtr; delete leftmost descendant */ } }

  47. treePtr 60 40 10 70 20 30 50 Case 1: treePtr Points to a Leaf 1) Delete the leaf 2) Set treePtr to NULL

  48. Case 1: treePtr Points to a Leaf /* delete leaf pointed to by treePtr */ delete treePtr; treePtr = NULL;

  49. treePtr delPtr 70 30 10 80 20 50 40 60 Case 2: treePtr Points to a Node with No leftChild 1) Save treePtr to delPtr 2) Set treePtr to treePtr -> rightChild 3) Delete node at delPtr

  50. Case 2: treePtr Points to a Node with No leftChild /* delete node at treePtr, making treePtr point to rightChild */ TreeNode *delPtr = treePtr; treePtr = treePtr -> rightChild; delPtr -> rightChild = NULL; delete delPtr;

More Related