递归解法:常规

  1. public List<Integer> preorderTraversal(TreeNode root) {
  2. List<Integer> list = new ArrayList<>();
  3. preOrder(root, list);
  4. return list;
  5. }
  6. private void preOrder(TreeNode root, List<Integer> list) {
  7. if (root == null) {
  8. return;
  9. }
  10. list.add(root.val);
  11. preOrder(root.left, list);
  12. preOrder(root.right, list);
  13. }
  14. public List<Integer> inorderTraversal(TreeNode root) {
  15. List<Integer> list = new ArrayList<>();
  16. inOrder(root, list);
  17. return list;
  18. }
  19. private void inOrder(TreeNode root, List<Integer> list) {
  20. if (root == null) {
  21. return;
  22. }
  23. inOrder(root.left, list);
  24. list.add(root.val);
  25. inOrder(root.right, list);
  26. }
  27. public List<Integer> postTraversal(TreeNode root) {
  28. List<Integer> list = new ArrayList<>();
  29. postOrder(root, list);
  30. return list;
  31. }
  32. private void postOrder(TreeNode root, List<Integer> list) {
  33. if (root == null) {
  34. return;
  35. }
  36. postOrder(root.left, list);
  37. postOrder(root.right, list);
  38. list.add(root.val);
  39. }

学习迭代解法:

前序遍历迭代

参考:
https://leetcode-cn.com/problems/binary-tree-preorder-traversal/solution/leetcodesuan-fa-xiu-lian-dong-hua-yan-shi-xbian-2/

  1. class Solution {
  2. public List<Integer> preorderTraversal(TreeNode root) {
  3. // 首先,要明确。前序遍历的迭代写法是用栈存放,然后按照中左右的顺序来弹出
  4. // 迭代过程中要始终保持这个顺序(循环迭代中自动帮忙保持)
  5. // Start!
  6. // 首先构造一个栈,用于遍历存放
  7. Stack<TreeNode> stack = new Stack<>();
  8. List<Integer> list = new ArrayList<>();
  9. if (root == null) {
  10. return list;
  11. }
  12. // 首先将根节点放入
  13. stack.push(root);
  14. // 循环迭代,因为迭代中是不停的弹出,然后入栈操作,只要不为空,就不结束
  15. while (!stack.isEmpty()) {
  16. // 每次迭代先取出栈顶元素
  17. TreeNode curNode = stack.pop();
  18. // 2个操作,第一,将这个值输出;第二,将它的右左子树入栈(如果有)
  19. list.add(curNode.val);
  20. if (curNode.right != null) {
  21. stack.push(curNode.right);
  22. }
  23. if (curNode.left != null) {
  24. stack.push(curNode.left);
  25. }
  26. }
  27. return list;
  28. }
  29. }

中序遍历迭代

  1. class Solution {
  2. public List<Integer> inorderTraversal(TreeNode root) {
  3. // 首先,还是通过栈来遍历迭代。
  4. // 一个特点是:对任何当前节点,都要一直先去找它的左节点。并不断加入栈(压在下面)
  5. // 直到左节点为空,才退出这个小迭代
  6. List<Integer> list = new ArrayList();
  7. if (root == null) {
  8. return list;
  9. }
  10. Stack<TreeNode> stack = new Stack();
  11. // 首先定义当前节点,并加入栈
  12. TreeNode curNode = root;
  13. // 进行大的迭代:1. 栈不为空 2. cur结点仍有指向
  14. // 因为用例证明[1,null,2,3]证明:1先入栈,然后弹出,没有新节点入栈。
  15. // 但是curNode指向了root的右节点,需要下一轮迭代。
  16. // 仅仅满足栈不为空不符合实际。
  17. while (!stack.isEmpty() || curNode != null) {
  18. // 一直找左节点!并加入
  19. while (curNode != null) {
  20. stack.push(curNode);
  21. curNode = curNode.left;
  22. }
  23. // 结束了就先POP一个出来,这个也就是最左侧完整左子树的左节点,第一个
  24. TreeNode node = stack.pop();
  25. list.add(node.val);
  26. // 如果当前节点有右子树,继续这样的迭代。类似模拟递归,保证右子树正常压入
  27. // 如果没有的话,下一伦迭代将弹出下一个应该弹出的值,直到结束
  28. if (node.right != null) {
  29. curNode = node.right;
  30. }
  31. }
  32. return list;
  33. }
  34. }

后序遍历迭代

  1. class Solution {
  2. public List<Integer> postorderTraversal(TreeNode root) {
  3. // 总体思路:使用2个栈,一个栈暂时保持,一个栈输出结果。
  4. // 因为输出结果栈必然要是左右中的输出,所以压入的时候要中右左压入。
  5. // 那么中间栈需要弹出按照中右左弹出
  6. // 因为我们在一开始时已经压入根节点,然后迭代开始时弹出这个根,再压入左右子树
  7. // 还是有一种模拟递归的感觉,每次迭代的时候都是先弹出最上层,也就是将根节点先压入结果栈
  8. // 然后再压入其左右子树。
  9. // 初始化操作
  10. Stack<TreeNode> tempStack = new Stack<>();
  11. Stack<TreeNode> resStack = new Stack<>();
  12. List<Integer> resList = new ArrayList<>();
  13. if (root == null) {
  14. return resList;
  15. }
  16. // 先压入根节点
  17. tempStack.push(root);
  18. // 开始迭代,临时栈为空退出
  19. while (!tempStack.isEmpty()) {
  20. // 压入结果栈,按照递归的思想就相当于:在结果栈中先压根,再右,再左。
  21. TreeNode curNode = tempStack.pop();
  22. resStack.push(curNode);
  23. // 在临时栈中压入左和右,弹出并压入结果栈的操作交由上面2行
  24. if (curNode.left != null) {
  25. // 不用担心节点是否需要移动,因为栈能准确弹出目标节点并指向
  26. tempStack.push(curNode.left);
  27. }
  28. if (curNode.right != null) {
  29. tempStack.push(curNode.right);
  30. }
  31. }
  32. while (!resStack.isEmpty()) {
  33. TreeNode resNode = resStack.pop();
  34. resList.add(resNode.val);
  35. }
  36. return resList;
  37. }
  38. }