一、题目
1、审题
2、分析
给出一棵二叉树,采用迭代输出先序遍历的节点值。
二、解答
1、思路:
方法一、
采用 Stack + 迭代的方式。
public List<Integer> preorderTraversal(TreeNode root) { List<Integer> result = new ArrayList<>(); if(root == null) return result; Stack<TreeNode> stack = new Stack<>(); stack.add(root); while(!stack.isEmpty()) { TreeNode node = stack.pop(); result.add(node.val); if(node.right != null) stack.add(node.right); if(node.left != null) stack.add(node.left); } return result; }
优化: Stack 只用于存储 Right 节点。
public List<Integer> preorderTraversal(TreeNode root) { List<Integer> result = new ArrayList<>(); if(root == null) return result; // 只存储右节点 Stack<TreeNode> rightStack = new Stack<>(); TreeNode node = root; while(node != null) { result.add(node.val); if(node.right != null) rightStack.add(node.right); node = node.left; if(node == null && !rightStack.isEmpty()) node = rightStack.pop(); } return result; }
方法二、
采用 InOrder 方式遍历,但输出为 InOrder 顺序。
public List<Integer> preorderTraversal(TreeNode root) { List<Integer> result = new ArrayList<>(); if(root == null) return result; Stack<TreeNode> stack = new Stack<>(); TreeNode node = root; while(node != null || !stack.isEmpty()) { while(node != null) { stack.push(node); result.add(node.val); node = node.left; } node = stack.pop(); node = node.right; } return result; }
方法三、
采用 Morris Traversal 方法线索二叉树,无需 Stack。
public List<Integer> preorderTraversal4(TreeNode root) { TreeNode cur = root; TreeNode pre = null; List<Integer> list = new ArrayList<>(); while(cur != null) { if(cur.left == null) { list.add(cur.val); cur = cur.right; } else { pre = cur.left; // 找到中序遍历时 cur 的前一个节点 while(pre.right != null && pre.right != cur) pre = pre.right; // 说明 cur 的左子树没访问过 if(pre.right == null) { // 添加索引 list.add(cur.val); pre.right = cur; cur = cur.left; } else { // cur 的前一个节点都访问过了,则删除索引 pre.right = null; cur = cur.right; } } } return list; }