后序遍历
方法一:
//后序遍历 void PostOrderWithoutRecursion(BTNode* root) { if (root == NULL) return; stack<btnode*> s; //pCur:当前访问节点,pLastVisit:上次访问节点 BTNode* pCur, *pLastVisit; //pCur = root; pCur = root; pLastVisit = NULL; //先把pCur移动到左子树最下边 while (pCur) { s.push(pCur); pCur = pCur->lchild; } while (!s.empty()) { //走到这里,pCur都是空,并已经遍历到左子树底端(看成扩充二叉树,则空,亦是某棵树的左孩子) pCur = s.top(); s.pop(); //一个根节点被访问的前提是:无右子树或右子树已被访问过 if (pCur->rchild == NULL || pCur->rchild == pLastVisit) { cout << setw(4) << pCur->data; //修改最近被访问的节点 pLastVisit = pCur; } /*这里的else语句可换成带条件的else if: else if (pCur->lchild == pLastVisit)//若左子树刚被访问过,则需先进入右子树(根节点需再次入栈) 因为:上面的条件没通过就一定是下面的条件满足。仔细想想! */ else { //根节点再次入栈 s.push(pCur); //进入右子树,且可肯定右子树一定不为空 pCur = pCur->rchild; while (pCur) { s.push(pCur); pCur = pCur->lchild; } } } cout << endl; }</btnode*>
方法二:
public void postOrderWithoutRecursion(TreeNode T){ Map<Object,Integer> flag = new HashMap<Object,Integer>(); //结点右孩子是否被遍历过的标记 Stack<TreeNode> stack = new Stack<TreeNode>(); TreeNode p; while(T!=null||!stack.empty()){ while(T!=null){ stack.push(T); flag.put(T.data, 0); //当结点被压入栈时,将value初始化为0 T = T.lchild; } if(!stack.empty()){ p = stack.peek(); if(p.rchild!=null&&flag.get(p.data)!=1){ T = p.rchild; flag.put(p.data, 1); //表示p结点的右孩子已经被遍历过 }else{ stack.pop(); System.out.println(p.data); } } } }