diff --git a/thu_dsa/chp5/binNode.h b/thu_dsa/chp5/binNode.h new file mode 100644 index 0000000..d6de521 --- /dev/null +++ b/thu_dsa/chp5/binNode.h @@ -0,0 +1,167 @@ +#ifndef BINNODE_H_ +#define BINNODE_H_ + +#include "../chp4/Stack.h" +#include "../chp4/Queue.h" + +#define BinNodePosi(T) BinNode* + +template +class BinNode{ +protected: + template + void visitAlongLeftBranch(VST &visit, Stack &S); + void goAlongLeftBranch(Stack &S); + +public: + BinNodePosi(T) parent; + BinNodePosi(T) leftChild; + BinNodePosi(T) rightChild; + T data; + int height; + int color; + int npl; + + //constructor + BinNode() : parent(nullptr), leftChild(nullptr), rightChild(nullptr), height(0), color(0), npl(0) {}; + BinNode(T const &val) : parent(nullptr), leftChild(nullptr), rightChild(nullptr), data(val), height(0), color(0), npl(0) {}; + + int size() const; //compute the size of the tree rooted at current node + BinNodePosi(T) insertAsLC(T const &val); //always assume that this.leftChild == nullptr + BinNodePosi(T) insertAsRC(T const &val); //always assume that this.rightChild == nullptr + BinNodePosi(T) succ() const; //return the direct successor of current node + + //tree traversal + template void preOrder_Re(VST &visit); + template void preOrder_It1(VST &visit); + template void preOrder_It2(VST &visit); + template void inOrder_Re(VST &visit); + template void inOrder_It(VST &visit); + template void postOrder_Re(VST &visit); + template void postOrder_It(VST &visit); + template void levelOrder(VST &visit); +}; + +//protected methods + +template template +void BinNode::visitAlongLeftBranch(VST &visit, Stack &S){ + BinNodePosi(T) curr = this; + while(curr){ + visit(curr->data); + S.push(curr->rightChild); + curr = curr->leftChild; + } +} + +template +void BinNode::goAlongLeftBranch(Stack &S){ + BinNodePosi(T) curr = this; + while (curr) { + S.push(curr); + curr = curr->leftChild; + } +} + +//public interfaces + +template +int BinNode::size() const { + int leftSize = this->leftChild ? this->leftChild->size() : 0; + int rightSize = this - rightChild ? this->rightChild->size() : 0; + return leftSize + rightSize + 1; +} + +template +BinNodePosi(T) BinNode::insertAsLC(T const &val){ + BinNodePosi(T) currNode = new BinNode(val); + currNode->parent = this; + this->leftChild = currNode; + + return currNode; +} + +template +BinNodePosi(T) BinNode::insertAsRC(T const &val){ + BinNodePosi(T) currNode = new BinNode(val); + currNode->parent = this; + this->rightChild = currNode; + + return currNode; +} + +//tree traversal + +template template +void BinNode::preOrder_Re(VST &visit){ + visit(this->data); + if(this->leftChild) this->leftChild->preOrder_Re(visit); + if(this->rightChild) this->rightChild->preOrder_Re(visit); +} + +template template +void BinNode::preOrder_It1(VST &visit) { + Stack S; + BinNodePosi(T) curr = this; + S.push(curr); + while(!S.empty()){ + curr = S.pop(); + visit(curr->data); + if(curr->rightChild) S.push(curr->rightChild); + if(curr->leftChild) S.push(curr->leftChild); + } +} + +template template +void BinNode::preOrder_It2(VST &visit){ + Stack S; + BinNodePosi(T) curr = this; + while(true){ + if (curr) curr->visitAlongLeftBranch(visit, S); + if (S.empty()) break; + curr = S.pop(); + } +} + +template template +void BinNode::inOrder_Re(VST &visit){ + if (this->leftChild) this->leftChild->inOrder_Re(visit); + visit(this->data); + if (this->rightChild) this->rightChild->inOrder_Re(visit); +} + +template template +void BinNode::inOrder_It(VST &visit){ + Stack S; + BinNodePosi(T) curr = this; + while(true){ + curr->goAlongLeftBranch(S); + if (S.empty()) break; + + curr = S.pop(); + visit(curr->data); + curr = curr->rightChild; + } +} + +template template +void BinNode::postOrder_Re(VST &visit){ + if (this->leftChild) this->leftChild->postOrder_Re(visit); + if (this->rightChild) this->rightChild->postOrder_Re(visit); + visit(this->data); +} + +template template +void BinNode::levelOrder(VST &visit){ + Queue q; + BinNodePosi(T) curr = this; + q.enqueue(curr); + while(!q.empty()){ + curr = q.dequeue(); + visit(curr->data); + if (curr->leftChild) q.enqueue(curr->leftChild); + if (curr->rightChild) q.enqueue(curr->rightChild); + } +} + +#endif diff --git a/thu_dsa/chp5/binTree.h b/thu_dsa/chp5/binTree.h new file mode 100644 index 0000000..7665390 --- /dev/null +++ b/thu_dsa/chp5/binTree.h @@ -0,0 +1,73 @@ +#ifndef BINTREE_H_ +#define BINTREE_H_ + +#include "binNode.h" + +#define MAX(X, Y) ((X)>(Y)?(X):(Y)) + +template +class BinTree{ +protected: + BinNodePosi(T) __root; + int __size; + bool updateHeight(BinNodePosi(T) x); + void updateHeightAbove(BinNodePosi(T) x); + +public: + //constructor + BinTree(): __root(nullptr), __size(0) {}; + + //deconstructor + ~BinTree()=default; + + bool empty() const { return __size == 0; } + int size() const { return __size; } + BinNodePosi(T) root() const { return __root; } + BinNodePosi(T) insertAsRoot(T const &val); + BinNodePosi(T) insertAsLC(BinNodePosi(T) x, T const &val); //always assume that this.leftChild == nullptr + BinNodePosi(T) insertAsRC(BinNodePosi(T) x, T const &val); //always assume that this.rightChild == nullptr + +}; + +//protected methods + +template +bool BinTree::updateHeight(BinNodePosi(T) x){ + int prevHeight = x->height; + int leftHeight = x->leftChild ? x->leftChild->height : -1; + int rightHeight = x->rightChild ? x->rightChild->height : -1; + x->height = MAX(leftHeight, rightHeight) + 1; + + return prevHeight != x->height; +} + +template +void BinTree::updateHeightAbove(BinNodePosi(T) x){ + for (; x && updateHeight(x); x = x->parent); +} + +//public interfaces + +template +BinNodePosi(T) BinTree::insertAsRoot(T const &val){ + __size = 1; + return __root = new BinNode(val); +} + +template +BinNodePosi(T) BinTree::insertAsLC(BinNodePosi(T) x, T const &val){ + ++__size; + BinNodePosi(T) res = x->insertAsLC(val); + updateHeightAbove(x); + return res; +} + +template +BinNodePosi(T) BinTree::insertAsRC(BinNodePosi(T) x, T const &val) { + ++__size; + BinNodePosi(T) res = x->insertAsRC(val); + updateHeightAbove(x); + return res; +} + +#endif diff --git a/thu_dsa/chp5/testBinTree.cpp b/thu_dsa/chp5/testBinTree.cpp new file mode 100644 index 0000000..b01544a --- /dev/null +++ b/thu_dsa/chp5/testBinTree.cpp @@ -0,0 +1,138 @@ +#include "binTree.h" +#include +#include + +using std::cout; +using std::endl; + +void test_insert(); +void test_preTraversal(); +void test_inTraversal(); +void test_postTraversal(); +void test_levelTraversal(); + +int main(){ + cout << "Running test." << endl; + + test_insert(); + test_preTraversal(); + test_inTraversal(); + test_postTraversal(); + test_levelTraversal(); + + cout << "All tests passed." << endl; + system("pause"); + return 0; +} + +void test_insert(){ + BinTree itree; + assert(itree.size() == 0); + assert(itree.empty()); + assert(itree.root() == nullptr); + + itree.insertAsRoot(8); + BinNodePosi(int) root = itree.root(); + assert(itree.size() == 1); + assert(!itree.empty()); + assert(root->data == 8); + assert(root->height == 0); + assert(root->leftChild == nullptr); + assert(root->rightChild == nullptr); + + itree.insertAsLC(root, 7); + itree.insertAsRC(root, 14); + BinNodePosi(int) left = root->leftChild; + BinNodePosi(int) right = root->rightChild; + assert(itree.size() == 3); + assert(root->height == 1); + assert(left->data == 7); + assert(right->data == 14); + assert(left->parent == root); + assert(right->parent == root); + assert(left->leftChild == nullptr); + assert(right->leftChild == nullptr); + assert(right->rightChild == nullptr); + assert(left->height == 0 && right->height == 0); +} + +template +struct Print{ + virtual void operator()(T const &val){ + cout << val << " "; + } +}; + +void test_preTraversal(){ + BinTree intTree; + cout << "tree pre-order traversal: " << endl; + + //construct a binary tree + BinNodePosi(int) root = intTree.insertAsRoot(8); + BinNodePosi(int) left = intTree.insertAsLC(root, 7); + BinNodePosi(int) right = intTree.insertAsRC(root, 14); + intTree.insertAsLC(left, 4); + intTree.insertAsRC(left, 3); + intTree.insertAsLC(right, 12); + intTree.insertAsRC(right, 18); + + root->preOrder_Re(Print()); + cout << endl; + root->preOrder_It1(Print()); + cout << endl; + root->preOrder_It2(Print()); + cout << endl; +} + +void test_inTraversal(){ + BinTree intTree; + cout << "tree in-order traversal: " << endl; + + //construct a binary tree + BinNodePosi(int) root = intTree.insertAsRoot(8); + BinNodePosi(int) left = intTree.insertAsLC(root, 7); + BinNodePosi(int) right = intTree.insertAsRC(root, 14); + intTree.insertAsLC(left, 4); + intTree.insertAsRC(left, 3); + intTree.insertAsLC(right, 12); + intTree.insertAsRC(right, 18); + + root->inOrder_Re(Print()); + cout << endl; + root->inOrder_It(Print()); + cout << endl; +} + +void test_postTraversal(){ + BinTree intTree; + cout << "tree post-order traversal: " << endl; + + //construct a binary tree + BinNodePosi(int) root = intTree.insertAsRoot(8); + BinNodePosi(int) left = intTree.insertAsLC(root, 7); + BinNodePosi(int) right = intTree.insertAsRC(root, 14); + intTree.insertAsLC(left, 4); + intTree.insertAsRC(left, 3); + intTree.insertAsLC(right, 12); + intTree.insertAsRC(right, 18); + + root->postOrder_Re(Print()); + cout << endl; +} + +void test_levelTraversal(){ + BinTree intTree; + cout << "tree level-order traversal: " << endl; + + //construct a binary tree + BinNodePosi(int) root = intTree.insertAsRoot(8); + BinNodePosi(int) left = intTree.insertAsLC(root, 7); + BinNodePosi(int) right = intTree.insertAsRC(root, 14); + intTree.insertAsLC(left, 4); + intTree.insertAsRC(left, 3); + intTree.insertAsLC(right, 12); + intTree.insertAsRC(right, 18); + + root->levelOrder(Print()); + cout << endl; +}