add thu_dsa/chp5/, with binNode.h, binTree.h & testBinTree.cpp, all tests passed.

This commit is contained in:
Shine wOng
2019-05-27 11:04:31 +08:00
parent 54b9e00caa
commit 58f9b08757
3 changed files with 378 additions and 0 deletions

167
thu_dsa/chp5/binNode.h Normal file
View File

@@ -0,0 +1,167 @@
#ifndef BINNODE_H_
#define BINNODE_H_
#include "../chp4/Stack.h"
#include "../chp4/Queue.h"
#define BinNodePosi(T) BinNode<T>*
template <typename T>
class BinNode{
protected:
template <typename VST>
void visitAlongLeftBranch(VST &visit, Stack<BinNodePosi(T)> &S);
void goAlongLeftBranch(Stack<BinNodePosi(T)> &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 <typename VST> void preOrder_Re(VST &visit);
template <typename VST> void preOrder_It1(VST &visit);
template <typename VST> void preOrder_It2(VST &visit);
template <typename VST> void inOrder_Re(VST &visit);
template <typename VST> void inOrder_It(VST &visit);
template <typename VST> void postOrder_Re(VST &visit);
template <typename VST> void postOrder_It(VST &visit);
template <typename VST> void levelOrder(VST &visit);
};
//protected methods
template <typename T> template <typename VST>
void BinNode<T>::visitAlongLeftBranch(VST &visit, Stack<BinNodePosi(T)> &S){
BinNodePosi(T) curr = this;
while(curr){
visit(curr->data);
S.push(curr->rightChild);
curr = curr->leftChild;
}
}
template <typename T>
void BinNode<T>::goAlongLeftBranch(Stack<BinNodePosi(T)> &S){
BinNodePosi(T) curr = this;
while (curr) {
S.push(curr);
curr = curr->leftChild;
}
}
//public interfaces
template <typename T>
int BinNode<T>::size() const {
int leftSize = this->leftChild ? this->leftChild->size() : 0;
int rightSize = this - rightChild ? this->rightChild->size() : 0;
return leftSize + rightSize + 1;
}
template <typename T>
BinNodePosi(T) BinNode<T>::insertAsLC(T const &val){
BinNodePosi(T) currNode = new BinNode<T>(val);
currNode->parent = this;
this->leftChild = currNode;
return currNode;
}
template <typename T>
BinNodePosi(T) BinNode<T>::insertAsRC(T const &val){
BinNodePosi(T) currNode = new BinNode<T>(val);
currNode->parent = this;
this->rightChild = currNode;
return currNode;
}
//tree traversal
template <typename T> template <typename VST>
void BinNode<T>::preOrder_Re(VST &visit){
visit(this->data);
if(this->leftChild) this->leftChild->preOrder_Re(visit);
if(this->rightChild) this->rightChild->preOrder_Re(visit);
}
template <typename T> template <typename VST>
void BinNode<T>::preOrder_It1(VST &visit) {
Stack<BinNodePosi(T)> 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 <typename T> template <typename VST>
void BinNode<T>::preOrder_It2(VST &visit){
Stack<BinNodePosi(T)> S;
BinNodePosi(T) curr = this;
while(true){
if (curr) curr->visitAlongLeftBranch(visit, S);
if (S.empty()) break;
curr = S.pop();
}
}
template <typename T> template <typename VST>
void BinNode<T>::inOrder_Re(VST &visit){
if (this->leftChild) this->leftChild->inOrder_Re(visit);
visit(this->data);
if (this->rightChild) this->rightChild->inOrder_Re(visit);
}
template <typename T> template <typename VST>
void BinNode<T>::inOrder_It(VST &visit){
Stack<BinNodePosi(T)> S;
BinNodePosi(T) curr = this;
while(true){
curr->goAlongLeftBranch(S);
if (S.empty()) break;
curr = S.pop();
visit(curr->data);
curr = curr->rightChild;
}
}
template <typename T> template <typename VST>
void BinNode<T>::postOrder_Re(VST &visit){
if (this->leftChild) this->leftChild->postOrder_Re(visit);
if (this->rightChild) this->rightChild->postOrder_Re(visit);
visit(this->data);
}
template <typename T> template <typename VST>
void BinNode<T>::levelOrder(VST &visit){
Queue<BinNodePosi(T)> 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

73
thu_dsa/chp5/binTree.h Normal file
View File

@@ -0,0 +1,73 @@
#ifndef BINTREE_H_
#define BINTREE_H_
#include "binNode.h"
#define MAX(X, Y) ((X)>(Y)?(X):(Y))
template <typename T>
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 <typename T>
bool BinTree<T>::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 <typename T>
void BinTree<T>::updateHeightAbove(BinNodePosi(T) x){
for (; x && updateHeight(x); x = x->parent);
}
//public interfaces
template <typename T>
BinNodePosi(T) BinTree<T>::insertAsRoot(T const &val){
__size = 1;
return __root = new BinNode<T>(val);
}
template <typename T>
BinNodePosi(T) BinTree<T>::insertAsLC(BinNodePosi(T) x, T const &val){
++__size;
BinNodePosi(T) res = x->insertAsLC(val);
updateHeightAbove(x);
return res;
}
template <typename T>
BinNodePosi(T) BinTree<T>::insertAsRC(BinNodePosi(T) x, T const &val) {
++__size;
BinNodePosi(T) res = x->insertAsRC(val);
updateHeightAbove(x);
return res;
}
#endif

View File

@@ -0,0 +1,138 @@
#include "binTree.h"
#include <iostream>
#include <cassert>
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<int> 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 <typename T>
struct Print{
virtual void operator()(T const &val){
cout << val << " ";
}
};
void test_preTraversal(){
BinTree<int> 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<int>());
cout << endl;
root->preOrder_It1(Print<int>());
cout << endl;
root->preOrder_It2(Print<int>());
cout << endl;
}
void test_inTraversal(){
BinTree<int> 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<int>());
cout << endl;
root->inOrder_It(Print<int>());
cout << endl;
}
void test_postTraversal(){
BinTree<int> 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<int>());
cout << endl;
}
void test_levelTraversal(){
BinTree<int> 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<int>());
cout << endl;
}