二叉树结点类,二叉树类;二叉树前序,中序,后序遍历(递归与非递归),层序遍历。
- DFS深度搜索算法
- 非递归前序遍历:访问左结点,保存左结点,使用栈。
- 非递归中序遍历:遇到结点入栈,遍历左子树;遍历完左子树,从栈定弹出结点,遍历右子树,使用栈。
- 非递归后序遍历:栈不空当前结点也不空,沿着左路下降入栈,如果从左边返回的然后处理邮编,如果从右边返回,访问该节点,使用栈。
- BFS宽度搜索算法
- 非递归层序遍历:使用队列。
值得学习的地方:友元类的定义;编程风格endwhile,endif;递归与非递归的转换
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
template <class T> class BinaryTree;
template <class T>
class BinaryTreeNode { // 二叉树结点类
friend class BinaryTree<T>; //声明二叉树为结点类的友元类,便于访问私有数据成员
private:
T info; //二叉树结点数据域
BinaryTreeNode<T>* left; //二叉树结点指向左子树的指针
BinaryTreeNode<T>* right; //二叉树结点指向左子树的指针
public:
BinaryTreeNode(); //缺省构造函数
BinaryTreeNode(const T& inf); //给定数据的构造函数
BinaryTreeNode(const T& inf, BinaryTreeNode<T>* l, BinaryTreeNode<T>* r);//给定了结点值和左右子树的构造函数
T value() const; //返回当前结点的数据
BinaryTreeNode<T>* leftchild() const; //返回当前结点左子树
BinaryTreeNode<T>* rightchild() const; //返回当前结点右子树
void setLeftchild(BinaryTreeNode<T>*) ; //设置当前结点的左子树
void setRightchild(BinaryTreeNode<T>*) ; //设置当前结点的右子树
void setValue(const T& val); //设置当前结点的数据域
bool isLeaf() const; //判定当前结点是否为叶结点,若是返回true
BinaryTreeNode<T>& operator = (const BinaryTreeNode<T>& Node){this = Node;};//重载赋值操作符
};
//****** BinaryTreeNode Implementation *******//
template<class T>
BinaryTreeNode<T>::BinaryTreeNode() {
left = right = NULL;
}
template<class T>
BinaryTreeNode<T>::BinaryTreeNode(const T& inf) { //给定数据的构造函数
info = inf;
left = right = NULL;
}
template<class T>
BinaryTreeNode<T>::BinaryTreeNode(const T& inf, BinaryTreeNode* l, BinaryTreeNode* r) {//给定数据的左右指针的构造函数
info = inf;
left = l;
right = r;
}
template<class T>
T BinaryTreeNode<T>::value() const {
return info;
}
template<class T>
BinaryTreeNode<T>* BinaryTreeNode<T>::leftchild() const { //返回当前结点指向左子树的指针
return left;
}
template<class T>
BinaryTreeNode<T>* BinaryTreeNode<T>::rightchild() const { //返回当前结点指向右子树的指针
return right;
}
template<class T>
void BinaryTreeNode<T>::setLeftchild(BinaryTreeNode<T>* subroot) { //设置当前结点的左子树
left = subroot;
}
template<class T>
void BinaryTreeNode<T>::setRightchild(BinaryTreeNode<T>* subroot) { //设置当前结点的右子树
right = subroot;
}
template<class T>
void BinaryTreeNode<T>::setValue(const T& val) { //设置当前结点的数据域
info = val;
}
template<class T>
bool BinaryTreeNode<T>::isLeaf() const { //判定当前结点是否为叶结点,若是返回true
return (left == NULL) && (right == NULL);
}
enum Tags{Left,Right}; //枚举类型
template <class T>
class StackElement { //StackElement
public:
BinaryTreeNode<T>* pointer;
Tags tag;
};
template <class T>
class BinaryTree {
private:
BinaryTreeNode<T>* root; //二叉树根结点
public:
BinaryTree(){root = NULL;}; //构造函数
~BinaryTree() {DeleteBinaryTree(root);}; //析构函数
bool isEmpty() const; //判定二叉树是否为空树
BinaryTreeNode<T>* Root(){return root;}; //返回二叉树根结点
BinaryTreeNode<T>* Parent(BinaryTreeNode<T>* current);//返回current的父结点
BinaryTreeNode<T>* LeftSibling(BinaryTreeNode<T>* current);
//返回current结点的左兄弟
BinaryTreeNode<T>* RightSibling(BinaryTreeNode<T>* current);
//返回current结点的右兄弟
void CreateTree(const T& info, BinaryTree<T>& leftTree, BinaryTree<T>& rightTree);
//构造一棵以info为根、leftTree和rightTree为左右子树的新二叉树
void PreOrder(BinaryTreeNode<T>* root); //递归前序周游二叉树或其子树
void InOrder(BinaryTreeNode<T>* root); //递归中序周游二叉树或其子树
void PostOrder(BinaryTreeNode<T>* root); //递归后序周游二叉树或其子树
void PreOrderWithoutRecursion(BinaryTreeNode<T>* root); //非递归前序周游二叉树或其子树
void InOrderWithoutRecursion(BinaryTreeNode<T>* root); //非递归中序周游二叉树或其子树
void PostOrderWithoutRecursion(BinaryTreeNode<T>* root);//非递归后序周游二叉树或其子树
void LevelOrder(BinaryTreeNode<T>* root); //按层次周游二叉树或其子树
void DeleteBinaryTree(BinaryTreeNode<T>* root); //删除二叉树或其子树
void Visit(T Value) {cout << Value;}; //访问
};
//********** BianryTree Implementation ***********//
template<class T>
bool BinaryTree<T>:: isEmpty() const { //判定二叉树是否为空树
return ( root? false : true);
}
template<class T>
BinaryTreeNode<T>* BinaryTree<T>::Parent(BinaryTreeNode<T>* current) {
using std::stack; //使用STL中的stack
stack<BinaryTreeNode<T>* > aStack;
BinaryTreeNode<T>* pointer = root; //保存输入参数
if(NULL != root && NULL != current) {
while(!aStack.empty() || pointer) {
if (pointer) {
if(current == pointer->leftchild() ||current == pointer->rightchild()) //如果当前pointer的孩子就是current,返回parent
return pointer;
aStack.push(pointer); //当前结点地址入栈
pointer = pointer->leftchild(); //当前链接结构指向左孩子
}
else { //左子树访问完毕,转向访问右子树
pointer = aStack.top(); //栈顶元素退栈
aStack.pop();
pointer = pointer->rightchild(); //当前链接结构指向右孩子
}//endif
} //endwhile
}//endif
}
template<class T>
BinaryTreeNode<T>* BinaryTree<T>::LeftSibling(BinaryTreeNode<T>* current) {
//返回current结点的左兄弟
if(current) {
BinaryTreeNode<T>* temp = Parent(current); //返回current结点的父结点
if ((temp == NULL) || current == temp->leftchild())
return NULL; //如果父结点为空,或者current没有左兄弟,返回空
else return temp->leftchild();
}
return NULL;
}
template<class T>
BinaryTreeNode<T>* BinaryTree<T>::RightSibling(BinaryTreeNode<T>* current) {
//返回current结点的右兄弟
if(current) {
BinaryTreeNode<T>* temp = Parent(current); //返回current结点的父结点
if(temp == NULL||current == temp->rightchild())
return NULL; //如果父结点为空,或者current没有右兄弟
else return temp->rightchild();
}
return NULL;
}
template<class T>
void BinaryTree<T>:: CreateTree (const T& info, BinaryTree<T>& leftTree, BinaryTree<T>& rightTree) {
//由左子树leftTree、右子树rightTree和数据元素info创建一棵新树,根结点是info
//其中this、leftTree、rightTree必须是不同的三棵树
root = new BinaryTreeNode<T>(info, leftTree.root, rightTree.root); //创建新树
leftTree.root = rightTree.root = NULL; //原来两棵子树的根结点指空,避免访问
}
template<class T>
void BinaryTree<T>:: DeleteBinaryTree(BinaryTreeNode<T>* root) { //以后序周游的方式删除二叉树
if(root) {
DeleteBinaryTree(root->left); //递归删除左子树
DeleteBinaryTree(root->right); //递归删除右子树
delete root; //删除根结点
}
}
template<class T>
void BinaryTree<T>::PreOrder (BinaryTreeNode<T>* root) { //前序周游二叉树
if(root != NULL) {
Visit(root->value()); //访问当前结点
PreOrder(root->leftchild()); //访问左子树
PreOrder(root->rightchild()); //访问右子树
}
}
template<class T>
void BinaryTree<T>:: InOrder (BinaryTreeNode<T>* root) { //中序周游二叉树
if(root != NULL) {
InOrder (root->leftchild()); //访问左子树
Visit(root->value()); //访问当前结点
InOrder (root->rightchild()); //访问右子树
}
}
template<class T>
void BinaryTree<T>:: PostOrder (BinaryTreeNode<T>* root) { //后序周游二叉树
if(root != NULL) {
PostOrder(root->leftchild()); //访问左子树
PostOrder (root->rightchild()); //访问右子树
Visit(root->value()); //访问当前结点
}
}
template<class T>
void BinaryTree<T>::PreOrderWithoutRecursion(BinaryTreeNode<T>* root) {//非递归前序周游二叉树或其子树
using std::stack; //使用STL中的stack
stack<BinaryTreeNode<T>* > aStack;
BinaryTreeNode<T>* pointer = root; //保存输入参数
while(!aStack.empty() || pointer) {
if (pointer) {
Visit(pointer->value()); //访问当前结点
aStack.push(pointer); //当前结点地址入栈
pointer = pointer->leftchild(); //当前链接结构指向左孩子
}
else { //左子树访问完毕,转向访问右子树
pointer = aStack.top(); //栈顶元素退栈
aStack.pop();
pointer = pointer->rightchild(); //当前链接结构指向右孩子
}//endif
} //endwhile
}
template<class T>
void BinaryTree<T>::InOrderWithoutRecursion(BinaryTreeNode<T>* root) {
//非递归中序周游二叉树或其子树
using std::stack; //使用STL中的stack
stack<BinaryTreeNode<T>* > aStack;
BinaryTreeNode<T>* pointer = root; //保存输入参数
while(!aStack.empty() || pointer) {
if (pointer) {
aStack.push(pointer); //当前结点地址入栈
pointer = pointer->leftchild(); //当前链接结构指向左孩子
}
else { //左子树访问完毕,转向访问右子树
pointer = aStack.top();
aStack.pop(); //栈顶元素退栈
Visit(pointer->value()); //访问当前结点
pointer = pointer->rightchild(); //当前链接结构指向右孩子
}
} //endwhile
}
template<class T>
void BinaryTree<T>::PostOrderWithoutRecursion(BinaryTreeNode<T>* root) {
//非递归后序周游二叉树或其子树
using std::stack; //使用STL栈部分
StackElement<T> element;
stack<StackElement<T > > aStack; //栈申明
BinaryTreeNode<T>* pointer;
if(root == NULL)
return; //空树即返回
else pointer = root; //保存输入参数
while (!aStack.empty() || pointer) {
while (pointer != NULL) {
element.pointer = pointer;
element.tag = Left;
aStack.push(element);
pointer = pointer->leftchild(); //沿左子树方向向下周游
}
element = aStack.top();
aStack.pop(); //托出栈顶元素
pointer = element.pointer;
if (element.tag == Left){
//从左子树回来
element.tag = Right;
aStack.push(element);
pointer = pointer->rightchild();
}
else { //从右子树回来
Visit(pointer->value()); //访问当前结点
pointer = NULL;
}
}
}
template<class T>
void BinaryTree<T>::LevelOrder(BinaryTreeNode<T>* root) {
//按层次周游二叉树或其子树
using std::queue; //使用STL的队列
queue<BinaryTreeNode<T>*> aQueue;
BinaryTreeNode<T>* pointer = root; //保存输入参数
if (pointer)
aQueue.push(pointer); //根结点入队列
while (!aQueue.empty()) { //队列非空
pointer = aQueue.front(); //取队列首结点
aQueue.pop(); //当前结点出队列
Visit(pointer->value()); //访问当前结点
if(pointer->leftchild())
aQueue.push(pointer->leftchild()); //左子树进队列
if(pointer->rightchild())
aQueue.push(pointer->rightchild()); //右子树进队列
}
}
int main() {
//建一棵树(如图5.5所示)
BinaryTree<char> a, b, c, d, e, f, g, h, i, nulltree;
d.CreateTree('D', nulltree, nulltree);
g.CreateTree('G', nulltree, nulltree);
h.CreateTree('H', nulltree, nulltree);
i.CreateTree('I', nulltree, nulltree);
f.CreateTree('F', h, i);
e.CreateTree('E', g, nulltree);
b.CreateTree('B', d, e);
c.CreateTree('C', nulltree, f);
a.CreateTree('A', b, c);
//前序周游二叉树
cout << "Preorder sequence is: "<<endl;
a.PreOrder(a.Root()); //递归
cout << endl;
cout << "Preorder sequence Without Recursion is: " <<endl;
a.PreOrderWithoutRecursion(a.Root()); //非递归
cout << endl;
//中序周游二叉树
cout << "Inorder sequence is: "<<endl;
a.InOrder(a.Root()); //递归
cout << endl;
cout << "Inorder sequence Without Recursion is: " <<endl;
a.InOrderWithoutRecursion(a.Root()); //非递归
cout << endl;
//后序周游二叉树
cout << "Postorder sequence is: "<<endl;
a.PostOrder(a.Root()); //递归
cout << endl;
cout << "Postorder sequence Without Recursion is: " <<endl;
a.PostOrderWithoutRecursion(a.Root()); //非递归
cout << endl;
//root
cout << "Root is: " << a.Root()->value() <<endl;
/* //delete tree
a.DeleteBinaryTree(a.Root());
cout<<"Tree is deleted."<<endl; //没有问题,在析构函数中调用
*/
return 0;
}