这里参考了课本配套的程序简单实现了二叉树类模板,主要包含了二叉树的创建和各种遍历方法。
对于二叉树的建立,这里使用的是前序遍历的方法创建的二叉树,具体如下:
这里我使用的下图中的二叉树作为测试案例:
具体不说了,详见代码吧。
源码
//test.cpp
#include <iostream>
#include "BinaryTree.h"
#include "BinaryTreeNode.h"
#include <vector>
using namespace std;
//前序方法递归创建二叉树
BinaryTreeNode<char>* createTree() {
BinaryTreeNode<char> *p;//这是使用局部变量是有风险的,函数结束后会被释放
char ch;
cin >> ch;
if (ch=='#'){
return NULL;
}
p = new BinaryTreeNode<char>(ch);
p->setLeftchild(createTree());
p->setRightchild(createTree());
return p;
}
void printTrsverse(const vector<char>& v) {
for (int i=0; i<v.size(); i++)
{
cout << v.at(i);
}
cout << endl;
}
//示例,输入"ABD##EG###C#FH##I##"
int main() {
BinaryTree<char> tr;
tr.Initialize(createTree());
vector<char> v;
v=tr.traversePreOrder();
cout << "前序递归遍历:" << endl;
printTrsverse(v);
v=tr.traverseInOrder();
cout << "中序递归遍历:" << endl;
printTrsverse(v);
v=tr.traversePostOrder();
cout << "后序递归遍历:" << endl;
printTrsverse(v);
v=tr.traversePreOrderWithoutRecusion();
cout << "前序非递归遍历:" << endl;
printTrsverse(v);
v=tr.traverseInOrderWithoutRecusion();
cout << "中序非递归遍历:" << endl;
printTrsverse(v);
v=tr.traversePostOrderWithoutRecusion();
cout << "后序非递归遍历:" << endl;
printTrsverse(v);
v=tr.traversePostOrderWithoutRecusion2();
cout << "后序非递归遍历2:" << endl;
printTrsverse(v);
v=tr.traverseLevelOrder();
cout << "层次遍历:" << endl;
printTrsverse(v);
return 0;
}
//BinaryTree.h
#pragma once
#include "BinaryTreeNode.h"
#include <stack>
#include <queue>
#include <vector>
using namespace std;
enum Tags{Left,Right};
template <class T>
class StackElement
{
public:
BinaryTreeNode<T>* pointer;
Tags tag;
};
template <class T>
class BinaryTree
{
private:
BinaryTreeNode<T>* root; //二叉树根结点指针
vector<T> elements; //用于保存遍历的元素
private:
void Visit(T elem) {elements.push_back(elem);}; //遍历访问元素的值
void PreOrder(BinaryTreeNode<T>* root); //从root前序遍历二叉树或其子树(递归部分)
void InOrder(BinaryTreeNode<T>* root); //从root中序遍历二叉树或其子树(递归部分)
void PostOrder(BinaryTreeNode<T>* root); //从root后序遍历二叉树或其子树(递归部分)
void PreOrderWithoutRecusion(BinaryTreeNode<T>* root); //从root非递归前序遍历二叉树或其子树(递归部分)
void InOrderWithoutRecusion(BinaryTreeNode<T>* root); //从root非递归中序遍历二叉树或其子树(递归部分)
void PostOrderWithoutRecusion(BinaryTreeNode<T>* root); //从root非递归后序遍历二叉树或其子树 (递归部分)
void PostOrderWithoutRecusion2(BinaryTreeNode<T>* root); //从root非递归后序遍历二叉树或其子树, 另一个版本(递归部分)
void LevelOrder(BinaryTreeNode<T>* root); //按层次遍历二叉树或其子树
BinaryTreeNode<T>* GetParent(BinaryTreeNode<T>* root,BinaryTreeNode<T>* current);//递归由root结点查找current结点的父结点
public:
BinaryTree(){root=NULL;}; //构造函数
virtual ~BinaryTree(){DeleteBinaryTree(root);}; //析构函数
bool isEmpty() const
{return ((root)?TRUE:FALSE);}; //判定二叉树是否为空树
void Initialize(BinaryTreeNode<T>* pointer) {root=pointer;};
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结点的右兄弟
//以elem作为根结点,leftTree作为树的左子树,rightTree作为树的右子树,构造一棵新的二叉树
void CreateTree(const T& elem, BinaryTree<T>& leftTree, BinaryTree<T>& rightTree);
void DeleteBinaryTree(BinaryTreeNode<T>* root); //递归删除二叉树或其子树
vector<T> traversePreOrder(); //从根节点前序遍历,以下依次对应
vector<T> traverseInOrder();
vector<T> traversePostOrder();
vector<T> traversePreOrderWithoutRecusion();
vector<T> traverseInOrderWithoutRecusion();
vector<T> traversePostOrderWithoutRecusion();
vector<T> traversePostOrderWithoutRecusion2();
vector<T> traverseLevelOrder();
};
template<class T>
BinaryTreeNode<T>* BinaryTree<T>::GetParent(BinaryTreeNode<T>* root,BinaryTreeNode<T>* current)
{
//从二叉树的root结点开始,查找current结点的父结点
BinaryTreeNode<T>* temp;
if(root==NULL)
return NULL;
//找到父结点
if((root->leftchild()==current)||(root->rightchild()==current))
return root;
//递归寻找父结点
if((temp=GetParent(root->leftchild(),current))!=NULL)
return temp;
else return GetParent(root->rightchild(),current);
}
template<class T>
BinaryTreeNode<T>* BinaryTree<T>::Parent(BinaryTreeNode<T>* current) //返回current结点的父结点指针
{
if((current==NULL)||(current==root))
return NULL; //空结点或者current为根结点时,返回NULL
return GetParent(root,current); //调用递归函数寻找父结点
}
template<class T>
BinaryTreeNode<T>* BinaryTree<T>::LeftSibling(BinaryTreeNode<T>* current) //返回current结点的左兄弟
{
if(current) //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) //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& elem, BinaryTree<T>& leftTree, BinaryTree<T>& rightTree) //以elem作为根结点,leftTree作为树的左子树,rightTree作为树的右子树,构造一棵新的二叉树
{
root=new BinaryTreeNode<T>(elem,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>
vector<T> BinaryTree<T>::traversePreOrder()
{
elements.clear();
PreOrder(root);
return elements;
}
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>
vector<T> BinaryTree<T>::traverseInOrder()
{
elements.clear();
InOrder(root);
return elements;
}
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>
vector<T> BinaryTree<T>::traversePostOrder()
{
elements.clear();
PostOrder(root);
return elements;
}
template<class T>
void BinaryTree<T>::PreOrderWithoutRecusion(BinaryTreeNode<T>* root)//非递归前序遍历二叉树或其子树
{
// using std::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(); //当前链接结构指向右孩子
} //else
} //while
}
template<class T>
vector<T> BinaryTree<T>::traversePreOrderWithoutRecusion()
{
elements.clear();
PreOrderWithoutRecusion(root);
return elements;
}
template<class T>
void BinaryTree<T>::InOrderWithoutRecusion(BinaryTreeNode<T>* root) //非递归中序遍历二叉树或其子树
{
// using std::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();
Visit(pointer->value()); //访问当前结点
pointer=pointer->rightchild(); //当前链接结构指向右孩子
aStack.pop(); //栈顶元素退栈
} //else
} //while
}
template<class T>
vector<T> BinaryTree<T>::traverseInOrderWithoutRecusion()
{
elements.clear();
InOrderWithoutRecusion(root);
return elements;
}
template<class T>
void BinaryTree<T>::PostOrderWithoutRecusion(BinaryTreeNode<T>* root)//非递归后序遍历二叉树或其子树
{
// using std::stack;
StackElement<T> element;
stack<StackElement<T > > aStack;
BinaryTreeNode<T>* pointer;
if(NULL==root)
return; //空树即返回
else pointer=root;
while(true)
{
//进入左子树
while(pointer!=NULL)
{
element.pointer=pointer;
element.tag=Left;
aStack.push(element);
pointer=pointer->leftchild();
}
//托出栈顶元素
element=aStack.top();
aStack.pop();
pointer=element.pointer;
//从右子树回来
while(element.tag==Right)
{
Visit(pointer->value()); //访问当前结点
if(aStack.empty())
return;
else
{
element=aStack.top();
aStack.pop();
pointer=element.pointer;
}
}
//从左子树回来
element.tag=Right;
aStack.push(element);
pointer=pointer->rightchild();
}
}
template<class T>
vector<T> BinaryTree<T>::traversePostOrderWithoutRecusion()
{
elements.clear();
PostOrderWithoutRecusion(root);
return elements;
}
template<class T>
void BinaryTree<T>::PostOrderWithoutRecusion2(BinaryTreeNode<T>* root)
{//非递归后序遍历二叉树或其子树, 另一个版本
// using std::stack;
stack<BinaryTreeNode<T>* > aStack;
BinaryTreeNode<T> *p, *q;
if(root==NULL)
return;
p=root;
do{
while(p!=NULL) //沿左路分支下降
{
aStack.push(p);
p=p->leftchild();
}
q=NULL;
while(!aStack.empty())
{
p=aStack.top();
aStack.pop();
if(p->rightchild()==q) //右子树为空或刚刚被访问过
{
Visit(p->value()); //访问当前结点
q=p;
}
else
{
aStack.push(p);
p=p->rightchild();
break;
}
}
}while(!aStack.empty());
}
template<class T>
vector<T> BinaryTree<T>::traversePostOrderWithoutRecusion2()
{
elements.clear();
PostOrderWithoutRecusion2(root);
return elements;
}
template<class T>
void BinaryTree<T>::LevelOrder(BinaryTreeNode<T>* root) //按层次遍历二叉树或其子树,这里使用队列来模拟
{
// using std::queue;
queue<BinaryTreeNode<T>*> aQueue;
BinaryTreeNode<T>* pointer=root;
if(pointer)
aQueue.push(pointer);
while(!aQueue.empty())
{
pointer=aQueue.front();
Visit(pointer->value()); //访问当前结点
aQueue.pop();
if(pointer->leftchild())
aQueue.push(pointer->leftchild());
if(pointer->rightchild())
aQueue.push(pointer->rightchild());
}
}
template<class T>
vector<T> BinaryTree<T>::traverseLevelOrder()
{
elements.clear();
LevelOrder(root);
return elements;
}
//BinaryTreeNode.h
#pragma once
template <class T> class BinaryTree;
template <class T>
class BinaryTreeNode
{
friend class BinaryTree<T>;
private:
T element; //二叉树结点数据域
BinaryTreeNode<T>* left; //二叉树结点指向左子树的指针
BinaryTreeNode<T>* right; //二叉树结点指向左子树的指针
public:
BinaryTreeNode();
BinaryTreeNode(const T& ele); //给定数据的构造函数
BinaryTreeNode(const T& ele,BinaryTreeNode* l, BinaryTreeNode* r);//给定数据的左右指针的构造函数
T value() const; //返回当前结点的数据
BinaryTreeNode<T>& operator= (const BinaryTreeNode<T>& Node)
{this=Node;}; //重载赋值操作符
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
};
template<class T>
BinaryTreeNode<T>::BinaryTreeNode()
{
left=right=NULL;
}
template<class T>
BinaryTreeNode<T>::BinaryTreeNode(const T& ele) //给定数据的构造函数
{
element=ele;
left=right=NULL;
}
template<class T>
BinaryTreeNode<T>::BinaryTreeNode(const T& ele,BinaryTreeNode* l, BinaryTreeNode* r)
//给定数据的左右指针的构造函数
{
element=ele;
left=l;
right=r;
}
template<class T>
T BinaryTreeNode<T>::value() const
{
return element;
}
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) //设置当前结点的数据域
{
element = val;
}
template<class T>
bool BinaryTreeNode<T>::isLeaf() const //判定当前结点是否为叶结点,若是返回true
{
return (left == NULL) && (right == NULL);
}
———————————2016.7.8记———————————————————————————–
上述test.cpp的createTree函数是有风险的,因为每次在函数内定义一个新结点,这样在函数结束时就被释放了。关于此问题很容易被忽视,详见:二叉树基础-由中根序列和后根序列重建二叉树(数据结构基础 第5周)