重点在于利用堆栈实现二叉树的前序、中序和后序非递归遍历。其中,前序、中序的非递归遍历实现相似,而后序非递归遍历有一定难度。此外,也要掌握利用队列实现二叉树的层序遍历。
#include<iostream >
#include<queue>
#include<stack>
using namespace std;
template <class T>
class BinaryNode
{
public:
BinaryNode(const T & theElement, BinaryNode<T> *lt = NULL, BinaryNode<T> *rt = NULL) :element(theElement), left(lt), right(rt){}
BinaryNode(){}
public:
T element;
BinaryNode<T>* left; //变量类型均需用T指定类型
BinaryNode<T>* right;
};
template<class T>
class BinaryTree
{
public:
BinaryTree(BinaryNode<T>* pRoot = NULL):root(pRoot){}
void CreateTree();
~BinaryTree();
void ReleaseTree();
void PreVisit_recur(){ cout << "递归前序遍历" << endl; _PreVisit_recur(&root); } //递归 前序遍历
void InVisit_recur(){ cout << "递归中序遍历" << endl; _InVisit_recur(&root); } //递归 中序遍历
void PostVisit_recur(){ cout << "递归后序遍历" << endl; _PostVisit_recur(&root); } //递归 后序遍历
void PreVisit_NoRecur();//非递归 前序遍历
void InVisit_NoRecur();//非递归中序遍历
void PostVisit_NoRecur();//非递归后序遍历
void layVisit(); //层次遍历
private:
BinaryNode<T> *root;
void _ReleaseTree(BinaryNode<T>**pRoot);
void _CreateTree(BinaryNode<T>**pRoot);
void _PreVisit_recur(BinaryNode<T>**pRoot); //递归 前序遍历 内部私有函数 需要传入参数是为了使用递归
void _InVisit_recur(BinaryNode<T>**pRoot); //递归 中序遍历
void _PostVisit_recur(BinaryNode<T>**pRoot); //递归 后序遍历
};
//内部私有函数 需要传入参数是为了使用递归
template<class T>
void BinaryTree<T>::_ReleaseTree(BinaryNode<T>**pRoot)
{
if (*pRoot != NULL)
{
_ReleaseTree(&(*pRoot)->left);
_ReleaseTree(&(*pRoot)->right);
delete *pRoot;
*pRoot = NULL;
}
}
template<class T>
void BinaryTree<T>::ReleaseTree()
{
_ReleaseTree(&root);
}
template<class T>
BinaryTree<T>::~BinaryTree()
{
_ReleaseTree(&root);
}
template<class T>
void BinaryTree<T>::_CreateTree(BinaryNode<T>**pRoot)
{
T data;
cin.clear();//清除错误状态
cin.sync(); //清除未读取数据
if(cin >> data)
{
*pRoot = new BinaryNode < T >() ;
(*pRoot)->element = data;
cout << "请输入 " << data << " 的左孩子" << endl;
_CreateTree(&((*pRoot)->left));
cout << "请输入 " << data << " 的右孩子" << endl;
_CreateTree(&((*pRoot)->right));
}
else
{
*pRoot = NULL;
}
}
template<class T>
void BinaryTree<T>::CreateTree()
{
ReleaseTree();
_CreateTree(&root);
}
template<class T>
void BinaryTree<T>::_PreVisit_recur(BinaryNode<T> **p)
{
if (*p != NULL)
{
cout << (*p)->element<<" ";
_PreVisit_recur(&((*p)->left));
_PreVisit_recur(&((*p)->right));
}
}
template<class T>
void BinaryTree<T>::_InVisit_recur(BinaryNode<T> **p)
{
if (*p != NULL)
{
_InVisit_recur(&((*p)->left));
cout << (*p)->element << " ";
_InVisit_recur(&((*p)->right));
}
}
template<class T>
void BinaryTree<T>::_PostVisit_recur(BinaryNode<T> **p)
{
if (*p != NULL)
{
_PostVisit_recur(&((*p)->left));
_PostVisit_recur(&((*p)->right));
cout << (*p)->element << " ";
}
}
template<class T>
void BinaryTree<T>::layVisit()
{
queue<BinaryNode<T>*> q;
int count = 0; //用于分层打印
int whole_size = 0; //用于每层一行的形式打印结果
cout << "层序遍历" << endl;
if (root != NULL)
{
q.push(root);
whole_size = 1;
}
while (!q.empty())
{
BinaryNode<T>* currP = q.front();
cout << currP->element << " ";
if (currP->left != NULL)
{
q.push(currP->left);
}
if (currP->right != NULL)
{
q.push(currP->right);
}
q.pop();
++count;
if (count == whole_size) //当弹出次数等于whole_size时,q的大小等于下一层元素个数
{
whole_size += q.size();
cout << endl;
}
}
}
template<class T>
void BinaryTree<T>::PreVisit_NoRecur()
{
stack<BinaryNode<T>*> s;
BinaryNode<T>*p = root;
cout << "非递归前序遍历" << endl;
while (p != NULL || !s.empty())
{
while (p != NULL)
{
cout << p->element << " ";
s.push(p);
p = p->left;
}
p = s.top();
p = p->right;
s.pop();
}
cout << endl;
}
template<class T>
void BinaryTree<T>::InVisit_NoRecur()//非递归中序遍历
{
stack<BinaryNode<T>*> s;
BinaryNode<T>*p = root;
cout << "非递归中序遍历" << endl;
while (p != NULL || !s.empty())
{
while (p != NULL)
{
s.push(p);
p = p->left;
}
p = s.top();
cout << p->element << " ";
p = p->right;
s.pop();
}
cout << endl;
}
/*对于后序遍历,每个结点在被访问时,要么其是叶子,要么其左孩子与右孩子均已经被访问
否则,则将该结点的左孩子与右孩子均入栈。
*/
template<class T>
void BinaryTree<T>::PostVisit_NoRecur()//非递归后序遍历
{
stack<BinaryNode<T>*> s;
BinaryNode<T>*p = root , *p_last = NULL;
cout << "非递归后序遍历" << endl;
if (p != NULL)
s.push(p);
else return;
while (!s.empty())
{
p = s.top();
//如果顶点结点是叶子或者其孩子均已被访问 ,则访问该节点 否则将其孩子入栈
if ((p->left == NULL && p->right == NULL) ||
(p->left == p_last || p->right == p_last)&& p_last != NULL)
{
cout << p->element << " ";
p_last = p;
s.pop();
}
else
{
if (p->right != NULL)
{
s.push(p->right);
}
if (p->left != NULL)
{
s.push(p->left);
}
}
}
}
int main()
{
BinaryTree<int> myTree;
myTree.CreateTree();
myTree.PreVisit_recur();
cout << endl;
myTree.InVisit_recur();
cout << endl;
myTree.PostVisit_recur();
cout << endl;
myTree.layVisit();
myTree.PreVisit_NoRecur();
myTree.InVisit_NoRecur();
myTree.PostVisit_NoRecur();
system("pause");
return 0;
}
运行结果
输入二叉树为:
1
/ \
2 3
/ \ \
4 5 6
/
7