给定一个二叉树,返回它的 前序 遍历。
示例:
输入: [1,null,2,3]
1
\
2
/
3
输出: [1,2,3]
进阶: 递归算法很简单,你可以通过迭代算法完成吗?
通过此题掌握二叉树的前序遍历,掌握Java泛型和栈的使用
题目分析:
二叉树的前序遍历,用递归遍历很容易实现,但如果用迭代算法就有一定的难度;
二叉树的前序遍历,顺序是——“根左右”(根节点,左子树,右子树),对于遍历,我们从根结点开始,访问到根结点入列表,接下来我们希望一直访问到的是左子树,右子树一定是最后访问到的,那当我们访问到右子树的时候我们此时并不需要将它入列表,那么就先将它入栈,等到需要它入列表的时候再取出来;
代码实现:
非递归:
public static class TreeNode { int data; TreeNode left; TreeNode right; TreeNode(int val) { data = val; } } /** * 非递归 */ public List<Integer> preorderTraversal(TreeNode root) { List<Integer> list = new ArrayList<>(); Stack<TreeNode> stack = new Stack<>(); if (root == null) return list; TreeNode node = root; while (node != null) { list.add(node.data); if (node.right != null) stack.push(node.right); if (node.left != null) { node = node.left; } else { if (stack.isEmpty()) break; else node = stack.pop(); } } return list; }
算法分析:
以主函数中构造的二叉树p为例:
1
/ \
2 3
/
4
- node = 1;进入while循环;node不为空,将节点1加入list,节点1的右孩子3不为空,将节点3入栈;
- node = node.left,现在node = 2;
- node不为空,继续循环;将节点2加入list,此时list = [1,2];节点2的右孩子为空,左孩子不为空,则node = node.left,现在node = 4;
- node不为空,继续循环;将节点4加入list,此时list = [1,2,4];节点4的左孩子和右孩子为空;栈非空,node = stack.pop(),此时node = 3;
- node不为空,继续循环;将节点3加入list,此时list = [1,2,4,3];节点4的左孩子和右孩子为空,node = node.left = null;栈为空,break,结束此次循环;
- node为空,while循环结束;
- 最后返回的结果就是:[1,2,4,3]
递归:
/** *递归 */ public List<Integer> preorderTraversal(TreeNode root) { List<Integer> list = new ArrayList<>(); if (root == null) return list; preorder(root,list); return list; } public static void preorder(TreeNode root, List list) { if (root != null) { list.add(root.data); preorder(root.left,list); preorder(root.right,list); } }
主函数:
public static void main(String[] args) { TreeNode p = new TreeNode(1); p.left = new TreeNode(2); p.right = new TreeNode(3); p.left.left = new TreeNode(4); Tree12 t = new Tree12(); List<Integer> list = t.preorderTraversal(p); for (int i = 0; i < list.size(); i++) { System.out.print(list.get(i) + " "); } }
运行结果:
1 2 4 3