二叉树的后序遍历非递归算法

1. 对于树的遍历我们最常用的三种遍历方法分别是前序遍历、中序遍历和后序遍历,使用的方法是深度优先遍历树的每一个节点,这些遍历方法都是使用递归函数来进行实现的,在数据量大的情况下是比较低效的,原因在于系统帮助我们调用了一个栈并且做了诸如保护现场和恢复现场等复杂的操作,才使得遍历可以使用非常简单的代码来实现,所以我们可以模仿系统中调用的栈自己可以来写一下栈,模仿其中的过程就可以完成对于三种遍历算法的实现,使用自定义的栈来代替系统栈可以得到效率上的提升,下面是对于后序遍历的非递归算法的实现

2. 首先模仿这个系统栈我们需要清楚的是系统栈为我们做了什么事情,下面以一棵二叉树为例来模仿其中的节点入栈与出栈的过程

创建的二叉树如下:

后序遍历为:5 3 2 4 1

先序遍历为:1 2 5 3 4

逆后序遍历为:1 4 2 3 5

从逆后序遍历与先序遍历的关系中我们可以知道逆后序遍历序列为先序遍历交换左右子树的遍历顺序得到的,所以我们得到了逆后序序列之后然后逆序就可以得到后序遍历的序列了,所以需要两个栈,第一个栈用来存储先序遍历交换左右子树的遍历的中介结果,第二个是存储后序遍历的结果(逆序也就是可以理解为先进后出的意思)

下面是模仿元素进栈与出栈的过程:

① 1节点进栈,在循环中弹出1节点压入到第二个栈中,发现左右节点不为空那么将左右节点压入栈1,这个与先序遍历中将左右子树压入到栈顶的顺序是相反的

② 弹出4节点压入到第二个栈中,发现左右孩子都为空那么不进行任何的操作

③ 弹出2节点压入到第二个栈中,发现左右节点不为空那么将左右节点压入到栈1中

④ 弹出3节点压入到第二个栈中,发现左右孩子都为空不进行任何操作

⑤ 弹出5节点压入到第二个栈中,发现左右孩子都为空不进行任何操作

最后栈为空那么退出循环结束

3. 具体的代码如下:

import java.util.Stack;
public class Main {
	public static void main(String[] args) {
		TreeNode<Integer> root = new TreeNode<Integer>(1);
		TreeNode<Integer> l = new TreeNode<Integer>(2);
		TreeNode<Integer> r = new TreeNode<Integer>(4);
		TreeNode<Integer> ll = new TreeNode<Integer>(5);
		TreeNode<Integer> lr = new TreeNode<Integer>(3);
		root.left = l;
		root.right = r;
		l.left = ll;
		l.right = lr;
		postOrder(root);
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static void postOrder(TreeNode<Integer> root) {
		Stack<TreeNode> src = new Stack<TreeNode>();
		Stack<TreeNode> res = new Stack<TreeNode>();
		src.push(root);
		while(!src.isEmpty()){
			TreeNode<Integer> p = src.pop();
			res.push(p);
			if(p.left != null){
				src.push(p.left);
			}
			if(p.right != null){
				src.push(p.right);
			}
		}
		//输出最终后序遍历的结果
		while(!res.isEmpty()){
			System.out.print(res.pop().val + " ");
		}	
	}

	public static class TreeNode<T>{
		T val;
		TreeNode<T> left;
		TreeNode <T> right;
		public TreeNode(T val) {
			super();
			this.val = val;
		}
	}
}
  • 52
    点赞
  • 124
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值