- 递归遍历
二叉树的遍历分为前序、中序、和后序,前中后代表双亲节点的位置。
简单基础题class Solution { public List<Integer> preorderTraversal(TreeNode root) { List<Integer> result = new ArrayList<Integer>(); preorder(root, result); return result; } public void preorder(TreeNode root, List<Integer> result) { if (root == null) { return; } result.add(root.val); preorder(root.left, result); preorder(root.right, result); } }
有一定的基础了,因此只给出前序遍历的代码。
- 迭代遍历
迭代遍历就是不利用递归用循环结构来实现对二叉树的遍历。
递归的底层逻辑是利用了栈的后进先出的结构来实现对二叉树的遍历,因此迭代遍历需要模拟递归运行的底层逻辑来进行。
以前序遍历为例,在递归遍历中,显然根节点是最先被压入栈中,然后是先弹出根节点,然后输出根节点的值,同时再将根的左右结点分别压入栈中,因为左节点需要先出栈,因此进栈顺序应该为右左,按照这一个逻辑循环当每个结点展开后以及每个结点都被弹出输出,最后栈会被清空,因此循环的结束条件就是栈为空的时候。 - 统一迭代
由于前序遍历的特殊性,在每个双亲结点被弹出展开之后,只需要将左右子节点重新压入栈中,双亲结点可以直接进行输出不再重新压入栈中。
但是,中序和后续遍历就无法这样,因为双亲结点并不是最先输出的,它需要按照输出的顺序重新被压入栈中保证遍历顺序的正确性。但是,在循环的过程中,遇到同一个结点时,我们无法确定这个结点此时应该进行展开还是进行弹出。
所以,我决定在展开后的双亲结点重新入栈的时候,在它入栈前先压入一个null表示null的下一个结点已经经过展开,此时为输出状态。经过这样的处理,前中后的迭代遍历写法,只需要将代码的顺序进行移动就可以实现遍历顺序的转换。class Solution { public List<Integer> postorderTraversal(TreeNode root) { Stack<TreeNode> stack=new Stack<TreeNode>(); List<Integer> res=new ArrayList<Integer>(); if(root!=null) stack.push(root); while(!stack.isEmpty()){ TreeNode cur=stack.pop(); if(cur!=null){ stack.push(cur); stack.push(null); if(cur.right!=null)stack.push(cur.right); if(cur.left!=null)stack.push(cur.left); }else{ res.add(stack.pop().val); } } return res; } }
以上是以后序遍历为例子,我在一开始思考迭代遍历时已经在往统一迭代的方向靠,因此在看了carl视频后结合自己的思考第一次写出的就是统一迭代代码。
代码随想录算法训练营day14|二叉树
最新推荐文章于 2024-10-01 23:05:47 发布