add thu_dsa/chp5/, with binNode.h, binTree.h & testBinTree.cpp, all tests passed.
This commit is contained in:
167
thu_dsa/chp5/binNode.h
Normal file
167
thu_dsa/chp5/binNode.h
Normal 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
73
thu_dsa/chp5/binTree.h
Normal 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
|
||||
138
thu_dsa/chp5/testBinTree.cpp
Normal file
138
thu_dsa/chp5/testBinTree.cpp
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user