数据结构-二叉树(3)二叉树遍历的非递归算法
不使用递归算法,想遍历二叉树:
#include <istream> #include "stack.h" #include "queue.h" using namespace std; void BinaryTree<T>::PreOrder(void (*visit)(BinTreeNode<T> *p)){ // 每次访问一个结点之后,用栈记录该结点的右子女,以便从左子女退回时可以直接从栈顶取得右子女的根结点,继续右子女的前序遍历 stack<BinTreeNode<T>*> S; BinTreeNode<T> *p=root; S.Push(NULL); while(p!=NULL){ visit(p); if(p->rightChild!=NULL) S.Push(p->rightChild); if(p->leftChild!=NULL) p=p->leftChild; else S.Pop(p); //左子树为空 } } template <class T> void BinaryTree<T>::PreOrder(void (*visit)(BinTreeNode<T> *p)){ // 另一种前序遍历的方法。进栈时先进右子树结点地址,再进左子树;出栈时相反。 stack<BinTreeNode<T>*> S; BinTreeNode<T> *p; S.Push(root); while (!S.IsEmpty()) { S.Pop(p);visit(p); if(p->rightChild!=NULL) S.Push(p->rightChild); if(p->leftChild!=NULL) S.Push(p->leftChild); } } template <class T> void BinTreeNode<T>::LevelOrder(void (*visit)(BinTreeNode<T> *p)){ // 利用队列进行层次性遍历 Queue<BinTreeNode<T>*> Q; BinTreeNode<T> *p=root; Q.EnQueue(p); while(!Q.IsEmpty()){ Q.DeQueue(p);visit(p); if(p->leftChild!=NULL) Q.EnQueue(p->leftChild); if(p->rightChild!=NULL) Q.EnQueue(p->rightChild); } } template <class T> void BinaryTree<T>::InOrder(void (*visit)(BinTreeNode<T> *p)){ // 利用栈进行中序遍历 stack<BinTreeNode<T>*> S; BinTreeNode<T> *p=root; do{ while(p!=NULL){ S.Push(p); p=p->leftChild; } if(!S.IsEmpty()){ S.Pop(p);visit(p); p=p->rightChild; } }while(p!=NULL || !S.IsEmpty()); //栈为空同时遍历指针也为空时结束循环 } template <class T> struct stkNode{ // 后序遍历时,必须借助栈结点结构,记录刚才是在左子树中还是右子树中 BinTreeNode<T> *ptr; enum tag{L,R}; stkNode(BinTreeNode<T> *N=NULL):ptr(N),tag(L){} } template <class T> void BinaryTree<T>::PostOrder(void (*visit)(BinTreeNode<T> *p)){ Stack<stkNode<T>> S; stkNode<T> w; BinTreeNode<T> *p=root; do{ while(p!=NULL){ w.ptr=p;w.tag=L;S.Push(w); p=p->leftChild; } int continue1=1; //继续循环标记,用于Case L情况结束小循环继续大循环。Case R情况继续小循环。 while(continue1 && !S.IsEmpty()){ S.Pop(w);p=w.ptr; switch(w.tag){ case L:w.tag=R;S.Push(w); continue1=0; p=p->rightChild; break; case R:visit(p); break; } } }while(!S.IsEmpty()); cout<<endl; }