二叉树的前序、中序、后序遍历的非递归实现

二叉树的前序、中序、后序遍历的非递归实现

  • 写在前面

    public class TreeNode {
      public int val;
      public TreeNode left;
      public TreeNode right;
    }
    

前序遍历

  • 实现一:使用单个栈完成

    public class Preorder {
      public List<Integer> preorder(TreeNode root) {
        if(root==null) return new ArrayList<>();
        Deque<TreeNode> stk = new ArrayDeque<>();
        List<Integer> result = new ArrayList<>();
        stk.push(root);
        while(!stk.isEmpty()) {
          TreeNode p = stk.pop();
          result.add(p.val);
          if(p.right!=null) stk.push(p.right);
          if(p.left!=null) stk.push(p.left);
        }
        return result;
      }
    }
    
  • 实现二:使用一个栈、一个指针完成

    public class Preorder {
      public List<Integer> preorder(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        Deque<TreeNode> stk = new ArrayDeque<>();
        TreeNode p = root;
        while(p!=null || !stk.isEmpty()) {
          if(p==null) p=stk.pop();
          result.add(p.val);
          if(p.right!=null) stk.push(p.right);
          p=p.left;
        }
        return result;
      }
    }
    
  • 实现三:只使用一个指针完成 - Morris

    public class Preorder {
      public List<Integer> preorder(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        TreeNode p = root;
        while(p!=null) {
          if(p.left==null) {
            result.add(p.val);
            p=p.right;
          } else {
            TreeNode q = p.left;
            while(q.right!=null && q.right!=p) q=q.right;
            if(q.right==null) {
              result.add(p.val);
              q.right=p;
              p=p.left;
            } else {
              q.right=null;
              p=p.right;
            }
          }
        }
        return result;
      }
    }
    

中序遍历

  • 实现一:使用两个栈完成

    public class Inorder {
      public List<Integer> inorder(TreeNode root) {
        if(root==null) return new ArrayList<>();
        List<Integer> result = new ArrayList<>();
        Deque<TreeNode> stk = new ArrayDeque<>();
        Deque<Boolean> stk2 = new ArrayDeque<>();
        stk.push(root);
        stk2.push(false);
        while(!stk.isEmpty()) {
          TreeNode p=stk.pop();
          boolean visited = stk2.pop();
          if(!visited) {
            stk.push(p);
            stk2.push(true);
            if(p.left!=null) {
              stk.push(p.left);
              stk2.push(false);
            }
          } else {
            result.add(p.val);
            if(p.right!=null) {
              stk.push(p.right);
              stk2.push(false);
            }
          }
        }
        return result;
      }
    }
    
  • 实现二:使用一个栈、一个指针完成

    public class Inorder {
      public List<Integer> inorder(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        Deque<TreeNode> stk = new ArrayDeque<>();
        TreeNode p = root;
        while(p!=null || !stk.isEmpty()) {
          if(p==null) {
            p=stk.pop();
            result.add(p.val);
            p=p.right;
          } else {
            stk.push(p);
            p=p.left;
          }
        }
        return result;
      }
    }
    
  • 实现三:只使用一个指针完成 - Morris

    public class Inorder {
      public List<Integer> inorder(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        TreeNode p = root;
        while(p!=null) {
          if(p.left==null) {
            result.add(p.val);
            p=p.right;
          } else {
            TreeNode q=p.left;
            while(q.right!=p && q.right!=null) q=q.right;
            if(q.right==null) {
              q.right=p;
              p=p.left;
            } else {
              q.right=null;
              result.add(p.val);
              p=p.right;
            }
          }
        }
        return result;
      }
    }
    

后序遍历

  • 实现一:使用两个栈实现

    public class Postorder {
      public List<Integer> postorder(TreeNode root) {
        if(root==null) return new ArrayList<>();
        List<Integer> result = new ArrayList<>();
        Deque<TreeNode> stk = new ArrayDeque<>();
        Deque<Integer> stk2 = new ArrayDeque<>();
        stk.push(root);
        stk2.push(0);
        while(!stk.isEmpty()) {
          TreeNode p=stk.pop();
          int visited = stk2.pop();
          if(visited==2) {
            result.add(p.val);
          } else if(visited==1) {
            stk.push(p);
            stk2.push(2);
            if(p.right!=null) {
              stk.push(p.right);
              stk2.push(0);
            }
          } else { // visited==0
            stk.push(p);
            stk2.push(1);
            if(p.left!=null) {
              stk.push(p.left);
              stk2.push(0);
            }
          }
        }
        return result;
      }
    }
    
  • 实现二:使用一个栈、两个指针实现

    public class Postorder {
      public List<Integer> postorder(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        Deque<TreeNode> stk = new ArrayDeque<>();
        TreeNode p=root, q=null;
        while(p!=null || !stk.isEmpty()) {
          if(p==null) {
            p=stk.pop();
            if(p.right==null || q==p.right) {
              result.add(p.val);
              q=p;
              p=null;
            } else {
              stk.push(p);
              p=p.right;
            }
          } else {
            stk.push(p);
            p=p.left;
          }
        }
        return result;
      }
    }
    
  • 实现三:使用一个指针实现(先得到逆序,再逆序),借助Morris的思想

    二叉树的后序遍历为LRN,与NRL得到的遍历顺序是完全相反的,因此我们先按NRL来遍历,将得到的结果逆序即可,而NRL的遍历顺序又与前序遍历类似,因此可以借助Morris的思想来实现

    public class Postorder {
      public List<Integer> postorder(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        TreeNode p=root;
        while(p!=null) {
          if(p.right==null) {
            result.add(p.val);
            p=p.left;
          } else {
            TreeNode q=p.right;
            while(q.left!=null && q.left!=p) q=q.left;
            if(q.left==null) {
    					result.add(p.val);
              q.left=p;
              p=p.right;
            } else {
              q.left=null;
              p=p.left;
            }
          }
        }
        Collections.reverse(result);
        return result;
      }
    }
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值