[牛客经典必刷算法题] LC7-非递归求二叉树的前序遍历

[牛客经典必刷算法题] LC7-非递归求二叉树的前序遍历

------------------------------本题链接---------------------------

题目描述

求给定的二叉树的前序遍历。
备注:用递归来解这道题很简单,你可以给出迭代的解法么?

示例

示例

输入
{1,#,2,3}
 
返回值
[1,2,3]

思路

上一题我们已经知道了如何递归地进行二叉树遍历
递归确实是一个很好理解的办法,但是调用函数需要做许多工作,比如准备函数内局部变量使用的空间、传递函数的参数等
每次调用函数都需要做这些事情,因此会产生额外开销导致递归效率偏低,所以逻辑上开销一致时递归的额外开销会更多一些
因而,我们有时会考虑用迭代的方法减小递归的开销

我们常常使用栈辅助树的遍历,而对于bfs则用队列辅助计算

这里我们用栈辅助

遍历框架

以下我们来总结一下非递归的遍历框架:

TreeNode设定如下

public class TreeNode {
 	int val = 0;
    TreeNode left = null;
    TreeNode right = null;
 }
先序遍历
public void preorderTraversal (TreeNode root) {
	Deque<TreeNode> stack = new LinkedList<TreeNode>();
	TreeNode tmp = root;
	while(tmp != null||!stack.isEmpty()){
		// 根节点存在,则操作根节点,再遍历其左节点和右节点
		if(tmp!=null){
	    	// 对根节点的主要操作
			func(tmp); // func()为遍历操作
			// 根节点入栈
	    	stack.push(tmp);
	    	// 遍历左节点
	        tmp = tmp.left;
	     }
	     // 节点不存在,寻找右节点
	     else {
	        tmp = stack.pop();
	        // 遍历右节点
	        tmp = tmp.right;
	     }
	}
}

另一种很简单的写法:

public void preorderTraversal (TreeNode root) {
	Deque<TreeNode> stack = new LinkedList<TreeNode>(){{ add(root); }};
	while(!stack.empty()){
		// 根节点出
	    TreeNode treeroot = stack.pop();
	    // 操作根节点
	    func(treeroot)
	    // 由于是栈,先装入右节点,再装入左节点
	    // 出栈时,则先遍历左节点,再遍历右节点
	    if(treeroot.right!=null)
	        stack.push(treeroot.right);
	    if(treeroot.left!=null)
	        stack.push(treeroot.left);
	}
}
中序遍历
public void inorderTraversal (TreeNode root) {
	Deque<TreeNode> stack = new LinkedList<TreeNode>();
	TreeNode tmp = root;
	while(tmp!=null||!stack.isEmpty()){
		// 迭代寻找左子节点
		if(tmp!=null){
			// 根节点入栈
	    	stack.push(tmp);
	    	// 遍历左节点
	        tmp = tmp.left;
	     }
	     // 左节点不存在,操作节点寻找右节点
	     else {
	     	// 遍历根节点
	        tmp = stack.pop();
	        // 对节点的主要操作
			func(tmp); // func()为遍历操作
	        // 遍历右节点
	        tmp = tmp.right;
	     }
    }
}
后序遍历
public void preorderTraversal (TreeNode root) {
	Deque<TreeNode> stack = new LinkedList<TreeNode>();
	TreeNode tmp = root, pre= root;
	while(tmp != null||!stack.isEmpty()){
		// 迭代寻找子节点
		while(tmp != null){
        	stack.push(tmp);
            tmp = tmp.left;
        }
	     // 左节点不存在,寻找右节点
	     if(!stack.isEmpty()){
            TreeNode treeroot = stack.peek().right;
            if(treeroot == null || treeroot == pre){
                tmp = stack.pop();
                // 对节点的主要操作
				func(tmp); // func()为遍历操作
                pre=tmp;
                tmp=null;
            }
            else{
                tmp = treeroot;
            }
        }
    }
}

有了以上框架,再看二叉树的遍历问题就比较简单了,套入框架就可以解答本题。

解答

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */

public class Solution {
    /**
     * 
     * @param root TreeNode类 
     * @return int整型ArrayList
     */
    private ArrayList<Integer> res;
    public ArrayList<Integer> preorderTraversal (TreeNode root) {
        res = new ArrayList<>();
        if(root == null) return res;
        Deque<TreeNode> stack = new LinkedList<TreeNode>(){{ add(root); }};

        while(!stack.isEmpty()){
            TreeNode tmp = stack.pop();
            res.add(tmp.val);
            if(tmp.right != null) stack.push(tmp.right);
            if(tmp.left != null) stack.push(tmp.left);
        }
        return res;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值