二叉树后序遍历的非递归算法
首次写博客,不知道有什么社区规矩没,不当之处请指正。
看到书上二叉树后序遍历的非递归算法需要一个退栈标记,不太喜欢这种做法,就尝试自己写了一下,验证了几次,遍历顺序都是对的,下面贴代码,若有细微难以发现的错误之处,还请诸位多多指教,本人初学算法,水平实在不咋地。。。。
1 LinkStack<TreeNode<T>*> stack; //自己写的链式栈 2 TreeNode<T>* p = subTree; 3 stack.push(p);//根节点入栈 4 while(!stack.isEmpty()) 5 { 6 if(p->leftChild == NULL && p->rightChild == NULL)//如果是叶节点,即访问之 7 { 8 visit(p); 9 stack.pop(); 10 if(!stack.isEmpty() && (stack.getTop().data ->leftChild == p || stack.getTop().data->rightChild == p)) 11 //如果退栈后的栈顶是原栈顶的父节点,继续退栈 12 { 13 while(!stack.isEmpty() && (stack.getTop().data ->leftChild == p || stack.getTop().data->rightChild == p)) 14 { 15 p = stack.getTop().data; 16 visit(p); 17 stack.pop(); 18 } 19 if(!stack.isEmpty()) 20 p = stack.getTop().data; 21 } 22 else 23 if(!stack.isEmpty()) 24 p = stack.getTop().data; 25 } 26 else//如果是非叶节点,即按照右子树,左子树的顺序进栈 27 { 28 if(p->rightChild != NULL) 29 { 30 stack.push(p->rightChild); 31 } 32 if(p->leftChild != NULL) 33 { 34 stack.push(p->leftChild); 35 } 36 p = stack.getTop().data; 37 } 38 }
总体的思想是:
- 后序遍历是先左子树,后右子树,最后根节点;每访问到一个节点,节点先如果非叶节点,按照右子树,左子树的顺序入栈,必能保证退栈时先访问左子树,然后右子树。
- 当首次循环到最左边的叶节点时,开始访问并退栈,并将退出的元素与新的栈顶比较;按照1中的顺序,如果新的栈顶不是退栈元素的父节点,只能是父节点的右子树,循环指针指向栈顶继续右子树的入栈操作(如果有的话);如果栈顶是退栈元素的父节点,表明此父节点的元素已经遍历完(有可能是右子树退回去的,也有可能是没有右子树,总之是遍历完了),可以访问此节点并继续退栈,如此循环。
- 对于根节点要特别注意,每次都要判断是不是栈空了,否则会有问题。
浙公网安备 33010602011771号