1 / 54

Trees 3: Construction of Dynamic Binary Trees

Trees 3: Construction of Dynamic Binary Trees. Andy Wang Data Structures, Algorithms, and Generic Programming. Overview. Definition of class TBinaryTree Recursive methods Inserting elements Removing elements Binary tree construction from file. Defining Class TBinaryTree.

qiana
Download Presentation

Trees 3: Construction of Dynamic Binary Trees

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 3: Construction of Dynamic Binary Trees Andy Wang Data Structures, Algorithms, and Generic Programming

  2. Overview • Definition of class TBinaryTree • Recursive methods • Inserting elements • Removing elements • Binary tree construction from file

  3. Defining Class TBinaryTree template <typename T> class TBinaryTree { friend class TBinaryTreeNavigator<T>; public: typedef T value_type; // constructors TBinaryTree(); virtual ~TBinaryTree(); TBinaryTree(const TBinaryTree<T>& B); TBinaryTree<T>& operator=(const TBinaryTree<T>& B); // read-only operations int Empty() const; size_t Size() const; int Height() const;

  4. Defining Class TBinaryTree void Display(std::ostream os, char ofc = ‘\0’) const; void Dump(std::ostream os, chcar ofc) const; void Dump(std::ostream os, const T& fill, char ofc) const; // operations int InsertRoot(const T& t); int InsertLeft(Navigator& N, const T& t); int InsertRight(Navigator& N, const T& t); int Insert(Iterator& I, const T& t); int Remove(Iterator& I); size_t Remove(const T& t); void Clear(); void Clear(Navigator &N); // clear subtree with root N

  5. Defining Class TBinaryTree // iterator operators typedef TBinaryTreeInorderIterator<T> Iterator; typedef TBinaryTreePreorderIterator<T> PreorderIterator; typedef TBinaryTreePostorderIterator<T> PostorderIterator; typedef TBinaryTreeLevelorderIterator<T> LevelorderIterator; typedef TBinaryTreeNavigator<T> Navigator; Navigator Root() const; Iterator Begin() const; Iterator End() const; Iterator rBegin() const; Iterator rBegin() const;

  6. Defining Class TBinaryTree protected: class TNode { friend class TBinaryTree<T>; friend class TBinaryTreeNavigator<T>; TNode(const T&); TNode(const TNode&); T value; char color; TNode *parent, *lchild, *rchild; }; TNode *root; static void RRelease(TNode *N); // recursive deletion of N’s children static TNode* RClone(const TNode *N); // deep copy of N static size_t RSize(const TNode *N); // return number of nodes at N static int RHeight(const TNode *N); // return height of tree at N };

  7. Recursive Protected Methods template <typename T> size_t TBinaryTree<T>::RSize(const TNode *N) { if (N == 0) return 0; return (1 + RSize(N->lchild) + RSize(N->rchild)); } template <typename T> int TBinaryTree<T>::RHeight(const TNode *N) { if (N == 0) return -1; return (1 + max(RHeight(N->lchild), RHeight(N->rchild))); }

  8. Recursive Protected Methods template <typename T> void TBinaryTree<T>::RRelease(TBinaryTree<T>::TNode *N) { if (N != 0) { if (N->lchild != 0) { TBinaryTree<T>::RRelease(N->lchild); delete N->lchild: N->lchild = 0; } if (N->rchild != 0) { TBinaryTree<T>::RRelease(N->rchild); delete N->rchild; N->rchild = 0; } } }

  9. Recursive Protected Methods template <typename T> TBinaryTree<T>::TNode* TBinaryTree<T>::RClone(const TBinaryTree<T>::TNode *N) { if (N == 0) return 0; TBinaryTree<T>::TNode *newN = new TBinaryTree<T>::TNode(N->value); newN->lchild = TBinaryTree<T>::RClone(N->lchild); newN->rchild = TBinaryTree<T>::RClone(N->rchild); if (newN->lchild) { newN->lchild->parent = newN; } if (newN->rchild) { newN->rchild->parent = newN; } return newN; }

  10. 1 root 2 3 4 5 Recursive Protected Calls template <typename T> void TBinaryTree<T>::Dump(ostream& os, const T& fill) const { // idea: BFS 1 root 2 3 4 5

  11. 1 root 2 3 4 5 6 7 Recursive Protected Calls template <typename T> void TBinaryTree<T>::Dump(ostream& os, const T& fill) const { if (root == 0) return; TBinaryTree<T>::TNode *fillNode = new TBinaryTree<T>::TNode(fill); CQueue<TList<TBinaryTree<T, P>::TNode *> > Que; TBinaryTree<T>::TNode *current; unsigned int currLayerSize, nextLayerSize, j, k; Que.Push(root); k = 1 // always 2^(layer number) for (curLayerSize = 1, nextLayerSize = 0; currLayerSize > 0; currLayerSize = nextLayerSize) {

  12. Recursive Protected Calls for (j = 0; j < k; ++j) { current = Que.Front(); Que.Pop(); os << current->value; if (current->lchild != 0) { Que.Push(current->lchild); ++nextLayerSize; } else { Que.Push(fillNode); } if (current->rchild != 0) { Que.Push(current->rchild); ++nextLayerSize; } else { Que.Push(fillNode); } } os << endl; k *= 2; }

  13. Recursive Protected Calls Que.Clear(); delete fillNode; }

  14. Helper Functions template <typename T> int TBinaryTree<T>::Empty() const { return (root == 0); } template <typename T> int TBinaryTree<T>::Height() const { return RHeight(root); } template <typename T> size_t TBinaryTree::Size() const { return RSize(root); } template <typename T> void TBinaryTree<T>::Clear() { TBinaryTree<T>::RRelease(root); delete root; root = 0; }

  15. Helper Functions template <typename T> void TBinaryTree<T>::Clear(TBinaryTreeNavigator<T>& N) { if (N.Valid()) { TNode *P = N.currentNode->parent; if (N.IsLeftChild()) { P->lchild = 0; } else if (N.IsRightChild()) { P->rchild = 0; } TBinaryTree<T>::RRelease(N.currNode); delete N.currNode; N.currNode = P; } }

  16. Helper Functions template <typename T> TBinaryTree<T>& TBinaryTree<T>::operator=(const TBinaryTree<T>& b) { if (this != &b) { Clear(); root = TBinaryTree<T>::RClone(b.root); } return *this; }

  17. Supports for Iterators and Navigators template <typename T> TBinaryTreeInorderIterator<T> TBinaryTree<T>::Begin() const { TBinaryTree<T>::Iterator I; I.Initialize(*this); return I; } template <typename T> TBinaryTreeInorderIterator<T> TBinaryTree<T>::End() const { TBinaryTree<T>::Iterator I; return I; }

  18. Supports for Iterators and Navigators template <typename T> TBinaryTreeInorderIterator<T> TBinaryTree<T>::rBegin() const { TBinaryTree<T>::Iterator I; I.rInitialize(*this); return I; } template <typename T> TBinaryTreeInorderIterator<T> TBinaryTree<T>::rEnd() const { TBinaryTree<T>::Iterator I; return I; } template <typename T> TBinaryTreeNavigator<T> TBinaryTree<T>::Root() const { TBinaryTree<T>::Navigator N; N.currNode = root; return N; }

  19. Constructors template <typename T> TBinaryTree<T>::TNode::TNode(const T& t) : value(t), color(‘b’), parent(0), lchild(0), rchild(0) { } template <typename T> TBinaryTree<T>::TNode::TNode(const TNode& N) { std::cerr << “TBinaryTree<T>::TNode::TNode(const TNode&) called\n” } template <typename T> TBinaryTree<T>::TBinaryTree() : root(0) { } template <typename T> TBinaryTree<T>::~TBinaryTree() { Clear(); } template <typename T> TBinaryTree<T>::TBinaryTree(const TBinaryTree<T>& b) { root = TBinaryTree<T>::RClone(b.root); }

  20. Tree Operations template <typename T> int TBinaryTree<T>::InsertRoot(const T& t) { if (root != 0) { root->value = t; return 1; } root = new TBinaryTree<T>::TNode(t); if (root == 0) { return 0; } return 1; }

  21. Tree Operations template <typename T> int TBinaryTree<T>::InsertLeft(Navigator& N, const T& t) { if (!N.Valid()) { return 0; } if (N.HasLeftChild()) { ++N; *N = t; return 1; } N.currNode->lchild = new TBinaryTree<T>::TNode(t); if (N.currNode->lchild == 0) { return 0; } N.currNode->lchild->parent = N.currNode; ++N; return 1; }

  22. Tree Operations template <typename T> int TBinaryTree<T>::InsertRight(Navigator& N, const T& t) { if (!N.Valid()) { return 0; } if (N.HasRightChild()) { N++; *N = t; return 1; } N.currNode->rchild = new TBinaryTree<T>::TNode(t); if (N.currNode->rchild == 0) { return 0; } N.currNode->rchild->parent = N.currNode; N++; return 1; }

  23. Tree Operations template <typename T> int TBinaryTree<T>::Insert(TBinaryTree<T>::Iterator& I, const T& Tval) { // empty case: insert at root if (Empty()) { if (InsertRoot(Tval) { I.N = Root(); return 1; } else { return 0; } }

  24. Tree Operations // valid case, insert Tval at I, move Told to ++I if (I.Valid()) { T Told = *I; Navigator N = I.N; if (N.HasRightChild())) { N++; while (N.HasLeftChild()) { ++N; } if (!InsertLeft(N, Told)) { return 0; } } else { if (!InsertRight(N, Told)) { return 0; } } *I = Tval; return 1; } Told I ->

  25. Tree Operations // valid case, insert Tval at I, move Told to ++I if (I.Valid()) { T Told = *I; Navigator N = I.N; if (N.HasRightChild())) { N++; while (N.HasLeftChild()) { ++N; } if (!InsertLeft(N, Told)) { return 0; } } else { if (!InsertRight(N, Told)) { return 0; } } *I = Tval; return 1; } Tval I -> Told

  26. Tree Operations // valid case, insert Tval at I, move Told to ++I if (I.Valid()) { T Told = *I; Navigator N = I.N; if (N.HasRightChild())) { N++; while (N.HasLeftChild()) { ++N; } if (!InsertLeft(N, Told)) { return 0; } } else { if (!InsertRight(N, Told)) { return 0; } } *I = Tval; return 1; } Told I ->

  27. Tree Operations // valid case, insert Tval at I, move Told to ++I if (I.Valid()) { T Told = *I; Navigator N = I.N; if (N.HasRightChild())) { N++; while (N.HasLeftChild()) { ++N; } if (!InsertLeft(N, Told)) { return 0; } } else { if (!InsertRight(N, Told)) { return 0; } } *I = Tval; return 1; } Tval I -> Told

  28. Tree Operations // invalid iterator: insert at the end; for (I.N = Root(); I.N.HasRightChild(); (I.N)++) { } if (InsertRight(I.N, Tval) { return 1; } else { I = End(); return 0; } }

  29. Tree Operations template <typename T> int TBinaryTree<T>::Remove(Iterator &I) { // remove element at I, leave I at ++(), and preserve inorder if (!I.Valid()) { return 0; } TBinaryTree<T>::Navigator N = I.N; ++I; // I is now at the next place in an inorder traversal TBinaryTree<T>::TNode *R = N.currNode->rchild; TBinaryTree<T>::TNode *L = N.currNode->lchild; TBinaryTree<T>::TNode *P = N.currNode->parent; N-> I->

  30. Tree Operations template <typename T> int TBinaryTree<T>::Remove(Iterator &I) { // remove element at I, leave I at ++(), and preserve inorder if (!I.Valid()) { return 0; } TBinaryTree<T>::Navigator N = I.N; ++I; // I is now at the next place in an inorder traversal TBinaryTree<T>::TNode *R = N.currNode->rchild; TBinaryTree<T>::TNode *L = N.currNode->lchild; TBinaryTree<T>::TNode *P = N.currNode->parent; N-> I->

  31. Tree Operations template <typename T> int TBinaryTree<T>::Remove(Iterator &I) { // remove element at I, leave I at ++(), and preserve inorder if (!I.Valid()) { return 0; } TBinaryTree<T>::Navigator N = I.N; ++I; // I is now at the next place in an inorder traversal TBinaryTree<T>::TNode *R = N.currNode->rchild; TBinaryTree<T>::TNode *L = N.currNode->lchild; TBinaryTree<T>::TNode *P = N.currNode->parent; P-> N-> L-> R-> I->

  32. Tree Operations • Nodes listed in inorder traversal before removal: L, N, I, R, … P • Nodes listed after removing N: • L, I, R, …P P-> N-> L-> R-> I->

  33. Tree Operations • Nodes listed in inorder traversal before removal: L, N, I, R, … P • Nodes listed after removing N: • L, I, R, …P • How do we reconnect L, P, and R? P-> L-> R-> I->

  34. R-> I-> Tree Operations • Nodes listed in inorder traversal before removal: L, N, I, R, … P • Nodes listed after removing N: • L, I, R, …P • How do we reconnect L, P, and R? P-> L->

  35. Tree Operations // case 1: N has right child if (N.HasRightChild()) { if (I.N.HasLeftChild()) { std::cerr << “Error: structural problem” << endl; return 0; } if (L) { I.N.currNode->lchild = L; L->parent = I.N.currNode; N.currNode->lchild = 0; } P-> N-> L-> R-> I->

  36. Tree Operations // case 1: N has right child if (N.HasRightChild()) { if (I.N.HasLeftChild()) { std::cerr << “Error: structural problem” << endl; return 0; } if (L) { I.N.currNode->lchild = L; L->parent = I.N.currNode; N.currNode->lchild = 0; } P-> N-> L-> R-> I->

  37. L-> Tree Operations // case 1: N has right child if (N.HasRightChild()) { if (I.N.HasLeftChild()) { std::cerr << “Error: structural problem” << endl; return 0; } if (L) { I.N.currNode->lchild = L; L->parent = I.N.currNode; N.currNode->lchild = 0; } P-> N-> R-> I->

  38. L-> Tree Operations // case 1: N has right child if (N.HasRightChild()) { if (I.N.HasLeftChild()) { std::cerr << “Error: structural problem” << endl; return 0; } if (L) { I.N.currNode->lchild = L; L->parent = I.N.currNode; N.currNode->lchild = 0; } P-> N-> R-> I->

  39. L-> Tree Operations if (N.IsLeftChild()) { P->lchild = R; R->parent = P; } else if (N.IsRightChild()) { P->rchild = R; R->parent = P; } else { root = R; R->parent = 0; } delete N.currNode; return 1; } P-> N-> R-> I->

  40. L-> Tree Operations if (N.IsLeftChild()) { P->lchild = R; R->parent = P; } else if (N.IsRightChild()) { P->rchild = R; R->parent = P; } else { root = R; R->parent = 0; } delete N.currNode; return 1; } P-> N-> R-> I->

  41. L-> Tree Operations if (N.IsLeftChild()) { P->lchild = R; R->parent = P; } else if (N.IsRightChild()) { P->rchild = R; R->parent = P; } else { root = R; R->parent = 0; } delete N.currNode; return 1; } P-> N-> R-> I->

  42. L-> Tree Operations if (N.IsLeftChild()) { P->lchild = R; R->parent = P; } else if (N.IsRightChild()) { P->rchild = R; R->parent = P; } else { root = R; R->parent = 0; } delete N.currNode; return 1; } P-> N-> R-> I->

  43. L-> Tree Operations if (N.IsLeftChild()) { P->lchild = R; R->parent = P; } else if (N.IsRightChild()) { P->rchild = R; R->parent = P; } else { root = R; R->parent = 0; } delete N.currNode; return 1; } P-> N-> R-> I->

  44. L-> Tree Operations if (N.IsLeftChild()) { P->lchild = R; R->parent = P; } else if (N.IsRightChild()) { P->rchild = R; R->parent = P; } else { root = R; R->parent = 0; } delete N.currNode; return 1; } P-> N-> R-> I->

  45. L-> Tree Operations if (N.IsLeftChild()) { P->lchild = R; R->parent = P; } else if (N.IsRightChild()) { P->rchild = R; R->parent = P; } else { root = R; R->parent = 0; } delete N.currNode; return 1; } N-> root-> R-> I->

  46. L-> Tree Operations if (N.IsLeftChild()) { P->lchild = R; R->parent = P; } else if (N.IsRightChild()) { P->rchild = R; R->parent = P; } else { root = R; R->parent = 0; } delete N.currNode; return 1; } N-> root-> R-> I->

  47. L-> Tree Operations if (N.IsLeftChild()) { P->lchild = R; R->parent = P; } else if (N.IsRightChild()) { P->rchild = R; R->parent = P; } else { root = R; R->parent = 0; } delete N.currNode; return 1; } N-> root-> R-> I->

  48. Tree Operations I-> P-> // case 2: N has no right child and has parent if (N.IsLeftChild()) { P->lchild = L; if (L) { L->parent = P; } } else if (N.IsRightChild()) { P->rchild = L; if (L) { L->parent = P } } else { // case 3: N has no right child and has no parent root = L; if (L) { L->parent = 0; } } delete N.currNode; return 1; } N-> L->

  49. L-> Tree Operations I-> P-> // case 2: N has no right child and has parent if (N.IsLeftChild()) { P->lchild = L; if (L) { L->parent = P; } } else if (N.IsRightChild()) { P->rchild = L; if (L) { L->parent = P } } else { // case 3: N has no right child and has no parent root = L; if (L) { L->parent = 0; } } delete N.currNode; return 1; }

  50. Tree Operations P-> // case 2: N has no right child and has parent if (N.IsLeftChild()) { P->lchild = L; if (L) { L->parent = P; } } else if (N.IsRightChild()) { P->rchild = L; if (L) { L->parent = P } } else { // case 3: N has no right child and has no parent root = L; if (L) { L->parent = 0; } } delete N.currNode; return 1; } N-> L->

More Related