当前位置:   article > 正文

“非递归” 实现二叉树的“前序、中序、后序、层序”遍历_不递归 先序遍历

不递归 先序遍历

目录

前言

一、前序遍历

二、后续遍历

三、中序遍历

四、层序遍历


前言


        相信学过或是了解过二叉树的朋友都知道,他的前序、中序、后序遍历使用递归法实现非常简单,那么如果使用非递归的方式来解,也就是使用迭代来解,你还能将他拿下么?实际上一点都不难,往下看~

一、前序遍历


前序遍历,就是按照 根结点->左节点->右节点 的顺序去访问,如果要使用非递归的方式去访问,我们就离不开一个重要的数据结构——“栈”(非常多适合用递归做的题用非递归的方式去做都是这样的思路),下面我们就来看看如何具体操作!

假设我们有二叉树的根节点 root,那么首先我们可以创建一个栈,将这个根节点放入栈中,接着,只要栈不为空,我们就进行循环,循环什么呢?每次 pop 出一个结点,只要这个结点右结点不为空就push压栈,接着左节点不为空就push压栈,这样循环,最后得到的就是线序遍历的结果。

Ps:因为是先序遍历,所以先从栈中弹出一个结点,接着压栈顺序是前右结点后左节点(原理:栈是先进后出的)。

力扣链接:144. 二叉树的前序遍历

根据这个链接,检验以下你是否能做对吧!

 代码如下:

  1. class Solution {
  2. public List<Integer> preorderTraversal(TreeNode root) {
  3. List<Integer> list = new ArrayList();
  4. if(root == null) {
  5. return list;
  6. }
  7. Stack<TreeNode> stack = new Stack();
  8. stack.push(root);
  9. while(!stack.isEmpty()) {
  10. TreeNode node = stack.pop();
  11. list.add(node.val);
  12. if(node.right != null) {
  13. stack.push(node.right);
  14. }
  15. if(node.left != null){
  16. stack.push(node.left);
  17. }
  18. }
  19. return list;
  20. }
  21. }

二、后续遍历


后序遍历实际上只需要在前序遍历的代码的基础上稍作修改即可~ 原本前序遍历的遍历顺序为"根 -> 左 -> 右",那么我们可以这样变一下,更改入栈的顺序,改成"根 -> 右 -> 左",也就是如下这几行代码进行一个转换

接着在对得到的数组进行反转,那么遍历顺序就变成了 "左 -> 右 -> 根",这正好就是我们要的后序遍历!

力扣链接:145. 二叉树的后序遍历

根据这个链接,检验以下你是否能做对吧!

代码如下:

  1. class Solution {
  2. public List<Integer> postorderTraversal(TreeNode root) {
  3. List<Integer> list = new ArrayList<>();
  4. if(root == null) {
  5. return list;
  6. }
  7. Stack<TreeNode> stack = new Stack();
  8. stack.push(root);
  9. while(!stack.isEmpty()) {
  10. TreeNode node = stack.pop();
  11. list.add(node.val);
  12. //这里和前序遍历调换顺序
  13. if(node.left != null) {
  14. stack.push(node.left);
  15. }
  16. if(node.right != null) {
  17. stack.push(node.right);
  18. }
  19. }
  20. Collections.reverse(list);
  21. return list;
  22. }
  23. }

三、中序遍历


中序遍历的迭代法思路就和 前序后序 不一样了,因为中序遍历的遍历顺序与读取结点的 val 值的顺序不一样~ 实际上,我们可以用 栈 来记录结点,用一个 cur指针 来遍历!

具体的,我们可以使用一个 cur指针 先指向根节点,然后进行循环,循环什么呢?当 cur指针 不为空时,就让 cur指针 一值向左走,边走边用栈记录下结点值,当 cur指针 为空时,我们就可以从栈中弹出元素给 cur指针 ,接着让 cur 指针向右结点走,接着循环以上步骤,直到 cur == null 并且 栈为空为止。

力扣链接:94. 二叉树的中序遍历

根据这个链接,检验以下你是否能做对吧!

代码如下:

  1. public List<Integer> inorderTraversal(TreeNode root) {
  2. List<Integer> list = new ArrayList<>();
  3. if(root == null) {
  4. return list;
  5. }
  6. Stack<TreeNode> stack = new Stack();
  7. TreeNode cur = root;
  8. while(cur != null || !stack.isEmpty()) {
  9. if(cur != null) {
  10. //让 cur 一路向左走,如果当前遍历元素不为空就入栈
  11. stack.push(cur);
  12. cur = cur.left;
  13. } else {
  14. //若当前元素为空,说明左边走到头了,这时候就可以弹出元素
  15. cur = stack.pop();
  16. list.add(cur.val);
  17. cur = cur.right;
  18. }
  19. }
  20. return list;
  21. }

四、层序遍历


这里便是经典的 BFS,层序遍历便是从上到下获取到每一层的数据,再将每一层依次从左到右打印。具体的,我们可以使用一个队列,首先将根结点入栈,然后用一个 size 记录下当前行的有多少个结点,通过这个 size 我们便可以直到需要弹出这一行多少元素,每弹出一个元素,就检查他的左右孩子是否为空(层序遍历,先左后右,顺序不可以颠倒),不为空就继续放入栈中

力扣链接:94. 二叉树的中序遍历

根据这个链接,检验以下你是否能做对吧!

代码如下:

  1. public List<List<Integer>> levelOrder(TreeNode root) {
  2. List<List<Integer>> ret = new ArrayList<>();
  3. if(root == null){
  4. return ret;
  5. }
  6. Queue<TreeNode> queue = new LinkedList<>();
  7. queue.offer(root);
  8. while(!queue.isEmpty()){
  9. int size = queue.size();
  10. //row为一行的数据
  11. List<Integer> row = new ArrayList<>();
  12. //确定一层的数据
  13. while(size > 0){
  14. TreeNode cur = queue.poll();
  15. row.add(cur.val);
  16. if(cur.left != null){
  17. queue.offer(cur.left);
  18. }
  19. if(cur.right != null){
  20. queue.offer(cur.right);
  21. }
  22. size--;
  23. }
  24. //添加一层的数据
  25. ret.add(row);
  26. }
  27. return ret;
  28. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/691122
推荐阅读
相关标签
  

闽ICP备14008679号