trees 3: construction of dynamic binary trees
DESCRIPTION
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. - PowerPoint PPT PresentationTRANSCRIPT
Trees 3: Construction Trees 3: Construction of Dynamic Binary of Dynamic Binary
TreesTrees
Andy WangAndy Wang
Data Structures, Algorithms, Data Structures, Algorithms, and Generic Programmingand Generic Programming
OverviewOverview
Definition of class TBinaryTreeDefinition of class TBinaryTree Recursive methodsRecursive methods Inserting elementsInserting elements Removing elementsRemoving elements Binary tree construction from fileBinary tree construction from file
Defining Class TBinaryTreeDefining Class TBinaryTreetemplate <typename T>template <typename T>
class TBinaryTree {class TBinaryTree {
friend class TBinaryTreeNavigator<T>;friend class TBinaryTreeNavigator<T>;
public:public:
typedef T value_type;typedef T value_type;
// constructors// constructors
TBinaryTree();TBinaryTree();
virtual ~TBinaryTree();virtual ~TBinaryTree();
TBinaryTree(const TBinaryTree<T>& B);TBinaryTree(const TBinaryTree<T>& B);
TBinaryTree<T>& operator=(const TBinaryTree<T>& B);TBinaryTree<T>& operator=(const TBinaryTree<T>& B);
// read-only operations// read-only operations
int Empty() const;int Empty() const;
size_t Size() const;size_t Size() const;
int Height() const;int Height() const;
Defining Class TBinaryTreeDefining Class TBinaryTreevoid Display(std::ostream os, char ofc = ‘\0’) const;void Display(std::ostream os, char ofc = ‘\0’) const;
void Dump(std::ostream os, chcar ofc) const;void Dump(std::ostream os, chcar ofc) const;
void Dump(std::ostream os, const T& fill, char ofc) const;void Dump(std::ostream os, const T& fill, char ofc) const;
// operations// operations
int InsertRoot(const T& t);int InsertRoot(const T& t);
int InsertLeft(Navigator& N, const T& t);int InsertLeft(Navigator& N, const T& t);
int InsertRight(Navigator& N, const T& t);int InsertRight(Navigator& N, const T& t);
int Insert(Iterator& I, const T& t);int Insert(Iterator& I, const T& t);
int Remove(Iterator& I);int Remove(Iterator& I);
size_t Remove(const T& t);size_t Remove(const T& t);
void Clear();void Clear();
void Clear(Navigator &N); // clear subtree with root Nvoid Clear(Navigator &N); // clear subtree with root N
Defining Class TBinaryTreeDefining Class TBinaryTree// iterator operators// iterator operators
typedef TBinaryTreeInorderIterator<T> Iterator;typedef TBinaryTreeInorderIterator<T> Iterator;
typedef TBinaryTreePreorderIterator<T> PreorderIterator;typedef TBinaryTreePreorderIterator<T> PreorderIterator;
typedef TBinaryTreePostorderIterator<T> PostorderIterator;typedef TBinaryTreePostorderIterator<T> PostorderIterator;
typedef TBinaryTreeLevelorderIterator<T> LevelorderIterator;typedef TBinaryTreeLevelorderIterator<T> LevelorderIterator;
typedef TBinaryTreeNavigator<T> Navigator;typedef TBinaryTreeNavigator<T> Navigator;
Navigator Root() const;Navigator Root() const;
Iterator Begin() const;Iterator Begin() const;
Iterator End() const;Iterator End() const;
Iterator rBegin() const;Iterator rBegin() const;
Iterator rBegin() const;Iterator rBegin() const;
Defining Class TBinaryTreeDefining Class TBinaryTreeprotected:protected:
class TNode {class TNode {
friend class TBinaryTree<T>;friend class TBinaryTree<T>;
friend class TBinaryTreeNavigator<T>;friend class TBinaryTreeNavigator<T>;
TNode(const T&);TNode(const T&);
TNode(const TNode&);TNode(const TNode&);
T value;T value;
char color;char color;
TNode *parent, *lchild, *rchild;TNode *parent, *lchild, *rchild;
};};
TNode *root;TNode *root;
static void RRelease(TNode *N); // recursive deletion of N’s childrenstatic void RRelease(TNode *N); // recursive deletion of N’s children
static TNode* RClone(const TNode *N); // deep copy of Nstatic TNode* RClone(const TNode *N); // deep copy of N
static size_t RSize(const TNode *N); // return number of nodes at Nstatic size_t RSize(const TNode *N); // return number of nodes at N
static int RHeight(const TNode *N); // return height of tree at Nstatic int RHeight(const TNode *N); // return height of tree at N
};};
Recursive Protected Recursive Protected MethodsMethods
template <typename T>template <typename T>
size_t TBinaryTree<T>::RSize(const TNode *N) {size_t TBinaryTree<T>::RSize(const TNode *N) {
if (N == 0) return 0;if (N == 0) return 0;
return (1 + RSize(N->lchild) + RSize(N->rchild));return (1 + RSize(N->lchild) + RSize(N->rchild));
}}
template <typename T>template <typename T>
int TBinaryTree<T>::RHeight(const TNode *N) {int TBinaryTree<T>::RHeight(const TNode *N) {
if (N == 0) return -1;if (N == 0) return -1;
return (1 + max(RHeight(N->lchild), RHeight(N->rchild)));return (1 + max(RHeight(N->lchild), RHeight(N->rchild)));
}}
Recursive Protected Recursive Protected MethodsMethods
template <typename T>template <typename T>
void TBinaryTree<T>::RRelease(TBinaryTree<T>::TNode *N) {void TBinaryTree<T>::RRelease(TBinaryTree<T>::TNode *N) {
if (N != 0) {if (N != 0) {
if (N->lchild != 0) {if (N->lchild != 0) {
TBinaryTree<T>::RRelease(N->lchild);TBinaryTree<T>::RRelease(N->lchild);
delete N->lchild:delete N->lchild:
N->lchild = 0;N->lchild = 0;
}}
if (N->rchild != 0) {if (N->rchild != 0) {
TBinaryTree<T>::RRelease(N->rchild);TBinaryTree<T>::RRelease(N->rchild);
delete N->rchild;delete N->rchild;
N->rchild = 0;N->rchild = 0;
}}
}}
}}
Recursive Protected Recursive Protected MethodsMethods
template <typename T>template <typename T>
TBinaryTree<T>::TNode* TBinaryTree<T>::TNode*
TBinaryTree<T>::RClone(const TBinaryTree<T>::TNode *N) {TBinaryTree<T>::RClone(const TBinaryTree<T>::TNode *N) {
if (N == 0) return 0;if (N == 0) return 0;
TBinaryTree<T>::TNode *newN = new TBinaryTree<T>::TNode(N->value);TBinaryTree<T>::TNode *newN = new TBinaryTree<T>::TNode(N->value);
newN->lchild = TBinaryTree<T>::RClone(N->lchild);newN->lchild = TBinaryTree<T>::RClone(N->lchild);
newN->rchild = TBinaryTree<T>::RClone(N->rchild);newN->rchild = TBinaryTree<T>::RClone(N->rchild);
if (newN->lchild) {if (newN->lchild) {
newN->lchild->parent = newN;newN->lchild->parent = newN;
}}
if (newN->rchild) {if (newN->rchild) {
newN->rchild->parent = newN;newN->rchild->parent = newN;
}}
return newN;return newN;
}}
Recursive Protected CallsRecursive Protected Callstemplate <typename T>template <typename T>
void TBinaryTree<T>::Dump(ostream& os, const T& fill) const {void TBinaryTree<T>::Dump(ostream& os, const T& fill) const {
// idea: BFS// idea: BFS
1
2 3
4 5
root 1
2 3
4 5
root
Recursive Protected CallsRecursive Protected Callstemplate <typename T>template <typename T>
void TBinaryTree<T>::Dump(ostream& os, const T& fill) const {void TBinaryTree<T>::Dump(ostream& os, const T& fill) const {
if (root == 0) return;if (root == 0) return;
TBinaryTree<T>::TNode *fillNode = new TBinaryTree<T>::TNode(fill);TBinaryTree<T>::TNode *fillNode = new TBinaryTree<T>::TNode(fill);
CQueue<TList<TBinaryTree<T, P>::TNode *> > Que;CQueue<TList<TBinaryTree<T, P>::TNode *> > Que;
TBinaryTree<T>::TNode *current;TBinaryTree<T>::TNode *current;
unsigned int currLayerSize, nextLayerSize, j, k;unsigned int currLayerSize, nextLayerSize, j, k;
Que.Push(root);Que.Push(root);
k = 1 // always 2^(layer number)k = 1 // always 2^(layer number)
for (curLayerSize = 1, nextLayerSize = 0; for (curLayerSize = 1, nextLayerSize = 0;
currLayerSize > 0;currLayerSize > 0;
currLayerSize = nextLayerSize) {currLayerSize = nextLayerSize) {
1
2 3
4 5 76
root
Recursive Protected CallsRecursive Protected Callsfor (j = 0; j < k; ++j) {for (j = 0; j < k; ++j) {
current = Que.Front();current = Que.Front();
Que.Pop();Que.Pop();
os << current->value;os << current->value;
if (current->lchild != 0) {if (current->lchild != 0) {
Que.Push(current->lchild);Que.Push(current->lchild);
++nextLayerSize;++nextLayerSize;
} else {} else {
Que.Push(fillNode);Que.Push(fillNode);
}}
if (current->rchild != 0) {if (current->rchild != 0) {
Que.Push(current->rchild);Que.Push(current->rchild);
++nextLayerSize;++nextLayerSize;
} else {} else {
Que.Push(fillNode);Que.Push(fillNode);
}}
}}
os << endl;os << endl;
k *= 2;k *= 2;
}}
Recursive Protected CallsRecursive Protected CallsQue.Clear();Que.Clear();
delete fillNode;delete fillNode;
}}
Helper FunctionsHelper Functionstemplate <typename T>template <typename T>
int TBinaryTree<T>::Empty() const { return (root == 0); }int TBinaryTree<T>::Empty() const { return (root == 0); }
template <typename T>template <typename T>
int TBinaryTree<T>::Height() const { return RHeight(root); }int TBinaryTree<T>::Height() const { return RHeight(root); }
template <typename T>template <typename T>
size_t TBinaryTree::Size() const { return RSize(root); }size_t TBinaryTree::Size() const { return RSize(root); }
template <typename T>template <typename T>
void TBinaryTree<T>::Clear() {void TBinaryTree<T>::Clear() {
TBinaryTree<T>::RRelease(root);TBinaryTree<T>::RRelease(root);
delete root;delete root;
root = 0;root = 0;
}}
Helper FunctionsHelper Functions
template <typename T>template <typename T>
void TBinaryTree<T>::Clear(TBinaryTreeNavigator<T>& N) {void TBinaryTree<T>::Clear(TBinaryTreeNavigator<T>& N) {
if (N.Valid()) {if (N.Valid()) {
TNode *P = N.currentNode->parent;TNode *P = N.currentNode->parent;
if (N.IsLeftChild()) {if (N.IsLeftChild()) {
P->lchild = 0;P->lchild = 0;
} else if (N.IsRightChild()) {} else if (N.IsRightChild()) {
P->rchild = 0;P->rchild = 0;
}}
TBinaryTree<T>::RRelease(N.currNode);TBinaryTree<T>::RRelease(N.currNode);
delete N.currNode;delete N.currNode;
N.currNode = P;N.currNode = P;
}}
}}
Helper FunctionsHelper Functions
template <typename T>template <typename T>
TBinaryTree<T>& TBinaryTree<T>::operator=(const TBinaryTree<T>& b) {TBinaryTree<T>& TBinaryTree<T>::operator=(const TBinaryTree<T>& b) {
if (this != &b) {if (this != &b) {
Clear();Clear();
root = TBinaryTree<T>::RClone(b.root);root = TBinaryTree<T>::RClone(b.root);
} }
return *this;return *this;
}}
Supports for Iterators and Supports for Iterators and NavigatorsNavigators
template <typename T>template <typename T>
TBinaryTreeInorderIterator<T> TBinaryTree<T>::Begin() const {TBinaryTreeInorderIterator<T> TBinaryTree<T>::Begin() const {
TBinaryTree<T>::Iterator I;TBinaryTree<T>::Iterator I;
I.Initialize(*this);I.Initialize(*this);
return I;return I;
}}
template <typename T>template <typename T>
TBinaryTreeInorderIterator<T> TBinaryTree<T>::End() const {TBinaryTreeInorderIterator<T> TBinaryTree<T>::End() const {
TBinaryTree<T>::Iterator I;TBinaryTree<T>::Iterator I;
return I;return I;
}}
Supports for Iterators and Supports for Iterators and NavigatorsNavigators
template <typename T>template <typename T>
TBinaryTreeInorderIterator<T> TBinaryTree<T>::rBegin() const {TBinaryTreeInorderIterator<T> TBinaryTree<T>::rBegin() const {
TBinaryTree<T>::Iterator I;TBinaryTree<T>::Iterator I;
I.rInitialize(*this);I.rInitialize(*this);
return I;return I;
}}
template <typename T>template <typename T>
TBinaryTreeInorderIterator<T> TBinaryTree<T>::rEnd() const {TBinaryTreeInorderIterator<T> TBinaryTree<T>::rEnd() const {
TBinaryTree<T>::Iterator I;TBinaryTree<T>::Iterator I;
return I;return I;
}}
template <typename T>template <typename T>
TBinaryTreeNavigator<T> TBinaryTree<T>::Root() const {TBinaryTreeNavigator<T> TBinaryTree<T>::Root() const {
TBinaryTree<T>::Navigator N;TBinaryTree<T>::Navigator N;
N.currNode = root;N.currNode = root;
return N;return N;
}}
ConstructorsConstructorstemplate <typename T>template <typename T>
TBinaryTree<T>::TNode::TNode(const T& t) : value(t), color(‘b’), parent(0), TBinaryTree<T>::TNode::TNode(const T& t) : value(t), color(‘b’), parent(0), lchild(0), rchild(0) {lchild(0), rchild(0) {
}}
template <typename T>template <typename T>
TBinaryTree<T>::TNode::TNode(const TNode& N) {TBinaryTree<T>::TNode::TNode(const TNode& N) {
std::cerr << “TBinaryTree<T>::TNode::TNode(const TNode&) called\n”std::cerr << “TBinaryTree<T>::TNode::TNode(const TNode&) called\n”
}}
template <typename T>template <typename T>
TBinaryTree<T>::TBinaryTree() : root(0) { }TBinaryTree<T>::TBinaryTree() : root(0) { }
template <typename T>template <typename T>
TBinaryTree<T>::~TBinaryTree() { Clear(); }TBinaryTree<T>::~TBinaryTree() { Clear(); }
template <typename T>template <typename T>
TBinaryTree<T>::TBinaryTree(const TBinaryTree<T>& b) {TBinaryTree<T>::TBinaryTree(const TBinaryTree<T>& b) {
root = TBinaryTree<T>::RClone(b.root);root = TBinaryTree<T>::RClone(b.root);
}}
Tree OperationsTree Operationstemplate <typename T>template <typename T>
int TBinaryTree<T>::InsertRoot(const T& t) {int TBinaryTree<T>::InsertRoot(const T& t) {
if (root != 0) {if (root != 0) {
root->value = t;root->value = t;
return 1;return 1;
}}
root = new TBinaryTree<T>::TNode(t);root = new TBinaryTree<T>::TNode(t);
if (root == 0) {if (root == 0) {
return 0;return 0;
}}
return 1;return 1;
}}
Tree OperationsTree Operationstemplate <typename T>template <typename T>
int TBinaryTree<T>::InsertLeft(Navigator& N, const T& t) {int TBinaryTree<T>::InsertLeft(Navigator& N, const T& t) {
if (!N.Valid()) {if (!N.Valid()) {
return 0;return 0;
}}
if (N.HasLeftChild()) {if (N.HasLeftChild()) {
++N;++N;
*N = t;*N = t;
return 1;return 1;
}}
N.currNode->lchild = new TBinaryTree<T>::TNode(t);N.currNode->lchild = new TBinaryTree<T>::TNode(t);
if (N.currNode->lchild == 0) {if (N.currNode->lchild == 0) {
return 0;return 0;
}}
N.currNode->lchild->parent = N.currNode;N.currNode->lchild->parent = N.currNode;
++N;++N;
return 1;return 1;
}}
Tree OperationsTree Operationstemplate <typename T>template <typename T>
int TBinaryTree<T>::InsertRight(Navigator& N, const T& t) {int TBinaryTree<T>::InsertRight(Navigator& N, const T& t) {
if (!N.Valid()) {if (!N.Valid()) {
return 0;return 0;
}}
if (N.HasRightChild()) {if (N.HasRightChild()) {
N++;N++;
*N = t;*N = t;
return 1;return 1;
}}
N.currNode->rchild = new TBinaryTree<T>::TNode(t);N.currNode->rchild = new TBinaryTree<T>::TNode(t);
if (N.currNode->rchild == 0) {if (N.currNode->rchild == 0) {
return 0;return 0;
}}
N.currNode->rchild->parent = N.currNode;N.currNode->rchild->parent = N.currNode;
N++;N++;
return 1;return 1;
}}
Tree OperationsTree Operationstemplate <typename T>template <typename T>
int TBinaryTree<T>::Insert(TBinaryTree<T>::Iterator& I, const T& Tval) {int TBinaryTree<T>::Insert(TBinaryTree<T>::Iterator& I, const T& Tval) {
// empty case: insert at root// empty case: insert at root
if (Empty()) {if (Empty()) {
if (InsertRoot(Tval) {if (InsertRoot(Tval) {
I.N = Root();I.N = Root();
return 1;return 1;
} else {} else {
return 0;return 0;
}}
}}
Tree OperationsTree Operations// valid case, insert Tval at I, move Told to ++I// valid case, insert Tval at I, move Told to ++I
if (I.Valid()) {if (I.Valid()) {
T Told = *I;T Told = *I;
Navigator N = I.N;Navigator N = I.N;
if (N.HasRightChild())) {if (N.HasRightChild())) {
N++;N++;
while (N.HasLeftChild()) {while (N.HasLeftChild()) {
++N;++N;
}}
if (!InsertLeft(N, Told)) {if (!InsertLeft(N, Told)) {
return 0;return 0;
}}
} else {} else {
if (!InsertRight(N, Told)) {if (!InsertRight(N, Told)) {
return 0;return 0;
}}
}}
*I = Tval;*I = Tval;
return 1;return 1;
}}
Told
I ->
Tree OperationsTree Operations// valid case, insert Tval at I, move Told to ++I// valid case, insert Tval at I, move Told to ++I
if (I.Valid()) {if (I.Valid()) {
T Told = *I;T Told = *I;
Navigator N = I.N;Navigator N = I.N;
if (N.HasRightChild())) {if (N.HasRightChild())) {
N++;N++;
while (N.HasLeftChild()) {while (N.HasLeftChild()) {
++N;++N;
}}
if (!InsertLeft(N, Told)) {if (!InsertLeft(N, Told)) {
return 0;return 0;
}}
} else {} else {
if (!InsertRight(N, Told)) {if (!InsertRight(N, Told)) {
return 0;return 0;
}}
}}
*I = Tval;*I = Tval;
return 1;return 1;
}}
Tval
I ->
Told
Tree OperationsTree Operations// valid case, insert Tval at I, move Told to ++I// valid case, insert Tval at I, move Told to ++I
if (I.Valid()) {if (I.Valid()) {
T Told = *I;T Told = *I;
Navigator N = I.N;Navigator N = I.N;
if (N.HasRightChild())) {if (N.HasRightChild())) {
N++;N++;
while (N.HasLeftChild()) {while (N.HasLeftChild()) {
++N;++N;
}}
if (!InsertLeft(N, Told)) {if (!InsertLeft(N, Told)) {
return 0;return 0;
}}
} else {} else {
if (!InsertRight(N, Told)) {if (!InsertRight(N, Told)) {
return 0;return 0;
}}
}}
*I = Tval;*I = Tval;
return 1;return 1;
}}
Told
I ->
Tree OperationsTree Operations// valid case, insert Tval at I, move Told to ++I// valid case, insert Tval at I, move Told to ++I
if (I.Valid()) {if (I.Valid()) {
T Told = *I;T Told = *I;
Navigator N = I.N;Navigator N = I.N;
if (N.HasRightChild())) {if (N.HasRightChild())) {
N++;N++;
while (N.HasLeftChild()) {while (N.HasLeftChild()) {
++N;++N;
}}
if (!InsertLeft(N, Told)) {if (!InsertLeft(N, Told)) {
return 0;return 0;
}}
} else {} else {
if (!InsertRight(N, Told)) {if (!InsertRight(N, Told)) {
return 0;return 0;
}}
}}
*I = Tval;*I = Tval;
return 1;return 1;
}}
Tval
I ->
Told
Tree OperationsTree Operations// invalid iterator: insert at the end;// invalid iterator: insert at the end;
for (I.N = Root(); I.N.HasRightChild(); (I.N)++) { }for (I.N = Root(); I.N.HasRightChild(); (I.N)++) { }
if (InsertRight(I.N, Tval) {if (InsertRight(I.N, Tval) {
return 1;return 1;
} else {} else {
I = End();I = End();
return 0;return 0;
}}
}}
Tree OperationsTree Operationstemplate <typename T>template <typename T>
int TBinaryTree<T>::Remove(Iterator &I) {int TBinaryTree<T>::Remove(Iterator &I) {
// remove element at I, leave I at ++(), and preserve inorder// remove element at I, leave I at ++(), and preserve inorder
if (!I.Valid()) {if (!I.Valid()) {
return 0;return 0;
}}
TBinaryTree<T>::Navigator N = I.N;TBinaryTree<T>::Navigator N = I.N;
++I; // I is now at the next place in an inorder traversal++I; // I is now at the next place in an inorder traversal
TBinaryTree<T>::TNode *R = N.currNode->rchild;TBinaryTree<T>::TNode *R = N.currNode->rchild;
TBinaryTree<T>::TNode *L = N.currNode->lchild;TBinaryTree<T>::TNode *L = N.currNode->lchild;
TBinaryTree<T>::TNode *P = N.currNode->parent;TBinaryTree<T>::TNode *P = N.currNode->parent;
N->I->
Tree OperationsTree Operationstemplate <typename T>template <typename T>
int TBinaryTree<T>::Remove(Iterator &I) {int TBinaryTree<T>::Remove(Iterator &I) {
// remove element at I, leave I at ++(), and preserve inorder// remove element at I, leave I at ++(), and preserve inorder
if (!I.Valid()) {if (!I.Valid()) {
return 0;return 0;
}}
TBinaryTree<T>::Navigator N = I.N;TBinaryTree<T>::Navigator N = I.N;
++I; // I is now at the next place in an inorder traversal++I; // I is now at the next place in an inorder traversal
TBinaryTree<T>::TNode *R = N.currNode->rchild;TBinaryTree<T>::TNode *R = N.currNode->rchild;
TBinaryTree<T>::TNode *L = N.currNode->lchild;TBinaryTree<T>::TNode *L = N.currNode->lchild;
TBinaryTree<T>::TNode *P = N.currNode->parent;TBinaryTree<T>::TNode *P = N.currNode->parent;
N->
I->
Tree OperationsTree Operationstemplate <typename T>template <typename T>
int TBinaryTree<T>::Remove(Iterator &I) {int TBinaryTree<T>::Remove(Iterator &I) {
// remove element at I, leave I at ++(), and preserve inorder// remove element at I, leave I at ++(), and preserve inorder
if (!I.Valid()) {if (!I.Valid()) {
return 0;return 0;
}}
TBinaryTree<T>::Navigator N = I.N;TBinaryTree<T>::Navigator N = I.N;
++I; // I is now at the next place in an inorder traversal++I; // I is now at the next place in an inorder traversal
TBinaryTree<T>::TNode *R = N.currNode->rchild;TBinaryTree<T>::TNode *R = N.currNode->rchild;
TBinaryTree<T>::TNode *L = N.currNode->lchild;TBinaryTree<T>::TNode *L = N.currNode->lchild;
TBinaryTree<T>::TNode *P = N.currNode->parent;TBinaryTree<T>::TNode *P = N.currNode->parent;
N->
L-> R->
I->
P->
Tree OperationsTree Operations
N->
L-> R->
I->
P->
Nodes listed in inorder traversal Nodes listed in inorder traversal before removal: L, N, I, R, … Pbefore removal: L, N, I, R, … P
Nodes listed after removing N:Nodes listed after removing N:– L, I, R, …PL, I, R, …P
Tree OperationsTree Operations
L-> R->
I->
P->
Nodes listed in inorder traversal Nodes listed in inorder traversal before removal: L, N, I, R, … Pbefore removal: L, N, I, R, … P
Nodes listed after removing N:Nodes listed after removing N:– L, I, R, …PL, I, R, …P
How do we reconnect How do we reconnect
L, P, and R?L, P, and R?
Tree OperationsTree Operations
L->
R->
I->
P->
Nodes listed in inorder traversal Nodes listed in inorder traversal before removal: L, N, I, R, … Pbefore removal: L, N, I, R, … P
Nodes listed after removing N:Nodes listed after removing N:– L, I, R, …PL, I, R, …P
How do we reconnect How do we reconnect
L, P, and R?L, P, and R?
Tree OperationsTree Operations// case 1: N has right child// case 1: N has right child
if (N.HasRightChild()) {if (N.HasRightChild()) {
if (I.N.HasLeftChild()) {if (I.N.HasLeftChild()) {
std::cerr << “Error: structural problem” << endl;std::cerr << “Error: structural problem” << endl;
return 0;return 0;
}}
if (L) {if (L) {
I.N.currNode->lchild = L;I.N.currNode->lchild = L;
L->parent = I.N.currNode;L->parent = I.N.currNode;
N.currNode->lchild = 0;N.currNode->lchild = 0;
}}
N->
L-> R->
I->
P->
Tree OperationsTree Operations// case 1: N has right child// case 1: N has right child
if (N.HasRightChild()) {if (N.HasRightChild()) {
if (I.N.HasLeftChild()) {if (I.N.HasLeftChild()) {
std::cerr << “Error: structural problem” << endl;std::cerr << “Error: structural problem” << endl;
return 0;return 0;
}}
if (L) {if (L) {
I.N.currNode->lchild = L;I.N.currNode->lchild = L;
L->parent = I.N.currNode;L->parent = I.N.currNode;
N.currNode->lchild = 0;N.currNode->lchild = 0;
}}
N->
L-> R->
I->
P->
Tree OperationsTree Operations// case 1: N has right child// case 1: N has right child
if (N.HasRightChild()) {if (N.HasRightChild()) {
if (I.N.HasLeftChild()) {if (I.N.HasLeftChild()) {
std::cerr << “Error: structural problem” << endl;std::cerr << “Error: structural problem” << endl;
return 0;return 0;
}}
if (L) {if (L) {
I.N.currNode->lchild = L;I.N.currNode->lchild = L;
L->parent = I.N.currNode;L->parent = I.N.currNode;
N.currNode->lchild = 0;N.currNode->lchild = 0;
}}
N->
L->
R->
I->
P->
Tree OperationsTree Operations// case 1: N has right child// case 1: N has right child
if (N.HasRightChild()) {if (N.HasRightChild()) {
if (I.N.HasLeftChild()) {if (I.N.HasLeftChild()) {
std::cerr << “Error: structural problem” << endl;std::cerr << “Error: structural problem” << endl;
return 0;return 0;
}}
if (L) {if (L) {
I.N.currNode->lchild = L;I.N.currNode->lchild = L;
L->parent = I.N.currNode;L->parent = I.N.currNode;
N.currNode->lchild = 0;N.currNode->lchild = 0;
}}
N->
L->
R->
I->
P->
Tree OperationsTree Operationsif (N.IsLeftChild()) {if (N.IsLeftChild()) {
P->lchild = R;P->lchild = R;
R->parent = P;R->parent = P;
} else if (N.IsRightChild()) {} else if (N.IsRightChild()) {
P->rchild = R;P->rchild = R;
R->parent = P;R->parent = P;
} else {} else {
root = R;root = R;
R->parent = 0;R->parent = 0;
}}
delete N.currNode;delete N.currNode;
return 1;return 1;
}}
N->
L->
R->
I->
P->
Tree OperationsTree Operationsif (N.IsLeftChild()) {if (N.IsLeftChild()) {
P->lchild = R;P->lchild = R;
R->parent = P;R->parent = P;
} else if (N.IsRightChild()) {} else if (N.IsRightChild()) {
P->rchild = R;P->rchild = R;
R->parent = P;R->parent = P;
} else {} else {
root = R;root = R;
R->parent = 0;R->parent = 0;
}}
delete N.currNode;delete N.currNode;
return 1;return 1;
}}
N->
L->
R->
I->
P->
Tree OperationsTree Operationsif (N.IsLeftChild()) {if (N.IsLeftChild()) {
P->lchild = R;P->lchild = R;
R->parent = P;R->parent = P;
} else if (N.IsRightChild()) {} else if (N.IsRightChild()) {
P->rchild = R;P->rchild = R;
R->parent = P;R->parent = P;
} else {} else {
root = R;root = R;
R->parent = 0;R->parent = 0;
}}
delete N.currNode;delete N.currNode;
return 1;return 1;
}}
N->
L->
R->
I->
P->
Tree OperationsTree Operationsif (N.IsLeftChild()) {if (N.IsLeftChild()) {
P->lchild = R;P->lchild = R;
R->parent = P;R->parent = P;
} } else if (N.IsRightChild()) {else if (N.IsRightChild()) {
P->rchild = R;P->rchild = R;
R->parent = P;R->parent = P;
} else {} else {
root = R;root = R;
R->parent = 0;R->parent = 0;
}}
delete N.currNode;delete N.currNode;
return 1;return 1;
}}
N->
L->
R->
I->
P->
Tree OperationsTree Operationsif (N.IsLeftChild()) {if (N.IsLeftChild()) {
P->lchild = R;P->lchild = R;
R->parent = P;R->parent = P;
} else if (N.IsRightChild()) {} else if (N.IsRightChild()) {
P->rchild = R;P->rchild = R;
R->parent = P;R->parent = P;
} else {} else {
root = R;root = R;
R->parent = 0;R->parent = 0;
}}
delete N.currNode;delete N.currNode;
return 1;return 1;
}}
N->
L->
R->
I->
P->
Tree OperationsTree Operationsif (N.IsLeftChild()) {if (N.IsLeftChild()) {
P->lchild = R;P->lchild = R;
R->parent = P;R->parent = P;
} else if (N.IsRightChild()) {} else if (N.IsRightChild()) {
P->rchild = R;P->rchild = R;
R->parent = P;R->parent = P;
} else {} else {
root = R;root = R;
R->parent = 0;R->parent = 0;
}}
delete N.currNode;delete N.currNode;
return 1;return 1;
}}
N->
L->
R->
I->
P->
Tree OperationsTree Operationsif (N.IsLeftChild()) {if (N.IsLeftChild()) {
P->lchild = R;P->lchild = R;
R->parent = P;R->parent = P;
} else if (N.IsRightChild()) {} else if (N.IsRightChild()) {
P->rchild = R;P->rchild = R;
R->parent = P;R->parent = P;
} else {} else {
root = R;root = R;
R->parent = 0;R->parent = 0;
}}
delete N.currNode;delete N.currNode;
return 1;return 1;
}}
N->
L->
R->
I->
root->
Tree OperationsTree Operationsif (N.IsLeftChild()) {if (N.IsLeftChild()) {
P->lchild = R;P->lchild = R;
R->parent = P;R->parent = P;
} else if (N.IsRightChild()) {} else if (N.IsRightChild()) {
P->rchild = R;P->rchild = R;
R->parent = P;R->parent = P;
} else {} else {
root = R;root = R;
R->parent = 0;R->parent = 0;
}}
delete N.currNode;delete N.currNode;
return 1;return 1;
}}
N->
L->
R->
I->
root->
Tree OperationsTree Operationsif (N.IsLeftChild()) {if (N.IsLeftChild()) {
P->lchild = R;P->lchild = R;
R->parent = P;R->parent = P;
} else if (N.IsRightChild()) {} else if (N.IsRightChild()) {
P->rchild = R;P->rchild = R;
R->parent = P;R->parent = P;
} else {} else {
root = R;root = R;
R->parent = 0;R->parent = 0;
}}
delete N.currNode;delete N.currNode;
return 1;return 1;
}}
N->
L->
R->
I->
root->
Tree OperationsTree Operations// case 2: N has no right child and has parent// case 2: N has no right child and has parent
if (N.IsLeftChild()) {if (N.IsLeftChild()) {
P->lchild = L;P->lchild = L;
if (L) {if (L) {
L->parent = P;L->parent = P;
}}
} else if (N.IsRightChild()) {} else if (N.IsRightChild()) {
P->rchild = L;P->rchild = L;
if (L) {if (L) {
L->parent = PL->parent = P
}}
} else { // case 3: N has no right child and has no parent} else { // case 3: N has no right child and has no parent
root = L;root = L;
if (L) {if (L) {
L->parent = 0;L->parent = 0;
}}
}}
delete N.currNode;delete N.currNode;
return 1;return 1;
}}
N->
L->
I-> P->
Tree OperationsTree Operations// case 2: N has no right child and has parent// case 2: N has no right child and has parent
if (N.IsLeftChild()) {if (N.IsLeftChild()) {
P->lchild = L;P->lchild = L;
if (L) {if (L) {
L->parent = P;L->parent = P;
}}
} else if (N.IsRightChild()) {} else if (N.IsRightChild()) {
P->rchild = L;P->rchild = L;
if (L) {if (L) {
L->parent = PL->parent = P
}}
} else { // case 3: N has no right child and has no parent} else { // case 3: N has no right child and has no parent
root = L;root = L;
if (L) {if (L) {
L->parent = 0;L->parent = 0;
}}
}}
delete N.currNode;delete N.currNode;
return 1;return 1;
}}
L->
I-> P->
Tree OperationsTree Operations// case 2: N has no right child and has parent// case 2: N has no right child and has parent
if (N.IsLeftChild()) {if (N.IsLeftChild()) {
P->lchild = L;P->lchild = L;
if (L) {if (L) {
L->parent = P;L->parent = P;
}}
} else if (N.IsRightChild()) {} else if (N.IsRightChild()) {
P->rchild = L;P->rchild = L;
if (L) {if (L) {
L->parent = PL->parent = P
}}
} else { // case 3: N has no right child and has no parent} else { // case 3: N has no right child and has no parent
root = L;root = L;
if (L) {if (L) {
L->parent = 0;L->parent = 0;
}}
}}
delete N.currNode;delete N.currNode;
return 1;return 1;
}}
N->
L->
P->
Tree OperationsTree Operations// case 2: N has no right child and has parent// case 2: N has no right child and has parent
if (N.IsLeftChild()) {if (N.IsLeftChild()) {
P->lchild = L;P->lchild = L;
if (L) {if (L) {
L->parent = P;L->parent = P;
}}
} else if (N.IsRightChild()) {} else if (N.IsRightChild()) {
P->rchild = L;P->rchild = L;
if (L) {if (L) {
L->parent = PL->parent = P
}}
} else { // case 3: N has no right child and has no parent} else { // case 3: N has no right child and has no parent
root = L;root = L;
if (L) {if (L) {
L->parent = 0;L->parent = 0;
}}
}}
delete N.currNode;delete N.currNode;
return 1;return 1;
}}
L->
P->
Tree OperationsTree Operations// case 2: N has no right child and has parent// case 2: N has no right child and has parent
if (N.IsLeftChild()) {if (N.IsLeftChild()) {
P->lchild = L;P->lchild = L;
if (L) {if (L) {
L->parent = P;L->parent = P;
}}
} else if (N.IsRightChild()) {} else if (N.IsRightChild()) {
P->rchild = L;P->rchild = L;
if (L) {if (L) {
L->parent = PL->parent = P
}}
} else { // case 3: N has no right child and has no parent} else { // case 3: N has no right child and has no parent
root = L;root = L;
if (L) {if (L) {
L->parent = 0;L->parent = 0;
}}
}}
delete N.currNode;delete N.currNode;
return 1;return 1;
}}
N->
L->
root->
Tree OperationsTree Operations// case 2: N has no right child and has parent// case 2: N has no right child and has parent
if (N.IsLeftChild()) {if (N.IsLeftChild()) {
P->lchild = L;P->lchild = L;
if (L) {if (L) {
L->parent = P;L->parent = P;
}}
} else if (N.IsRightChild()) {} else if (N.IsRightChild()) {
P->rchild = L;P->rchild = L;
if (L) {if (L) {
L->parent = PL->parent = P
}}
} else { // case 3: N has no right child and has no parent} else { // case 3: N has no right child and has no parent
root = L;root = L;
if (L) {if (L) {
L->parent = 0;L->parent = 0;
}}
}}
delete N.currNode;delete N.currNode;
return 1;return 1;
}}
L->root->
Tree OperationsTree Operationstemplate <typename T>template <typename T>
size_t TBinaryTree<T>::Remove(const T& t) {size_t TBinaryTree<T>::Remove(const T& t) {
size_t count(0);size_t count(0);
TBinaryTree<T>::Iterator I = Begin();TBinaryTree<T>::Iterator I = Begin();
while (I.Valid()) {while (I.Valid()) {
if (t == *I) {if (t == *I) {
Remove(I);Remove(I);
++count;++count;
} else {} else {
++I;++I;
}}
}}
return count;return count;
}}