当前位置:   article > 正文

二叉树遍历方法——前、中、后序遍历(java)_二叉树遍历前序中序后序java

二叉树遍历前序中序后序java

二叉树结构:

  1. static class TreeNode{
  2. public char val;
  3. public TreeNode left;
  4. public TreeNode right;
  5. public TreeNode(char val) {
  6. this.val = val;
  7. }
  8. @Override
  9. public String toString() {
  10. return this.val+"";
  11. }
  12. }

一、前序遍历

前序遍历是一种访问二叉树的每一个结点的方法,它的遍历顺序是根节点,左子树,右子树。

1)递归版本

  1. public void preOrder1(TreeNode root){
  2. if(root==null){
  3. return ;
  4. }
  5. System.out.println(root.val);
  6. preOrder1(root.left);
  7. preOrder1(root.right);
  8. }

递归版本其实很简单,就是按照它的遍历方式来写一下就可以,我们主要来介绍一下非递归的方法。

2)非递归版本

前序遍历的非递归方式就是将递归的版本的每一个过程都存储下来,而我们就需要一个辅助栈来帮助我们实现。

算法思想:

1.节点不为空,打印,入栈,遍历左子树

2.节点为空但是栈不为空,出栈顶元素,遍历栈顶元素右子树

3.节点为空栈也为空,结束程序

4.二叉树为空结束程序

按照上述的代码思路,我们可以实现代码如下:

  1. public void preOrder2(TreeNode root){
  2. Stack<TreeNode> stack = new Stack<>();
  3. TreeNode cur = root;
  4. while(!stack.empty()||cur!=null){
  5. if(cur!=null){
  6. //打印根节点
  7. System.out.print(cur.val+" ");
  8. //根节点入栈
  9. stack.push(cur);
  10. //访问左子树
  11. cur=cur.left;
  12. }
  13. else{
  14. cur=stack.pop().right;
  15. }
  16. }
  17. }

运行结果:

 二、中序遍历

中序遍历的顺序是左子树、根节点、右子树,所以递归的版本可以按照前序遍历的思路来实现。

1)递归版本

  1. public void inOrder1(TreeNode root){
  2. if(root==null){
  3. return ;
  4. }
  5. inOrder1(root.left);
  6. System.out.print(root.val+" ");
  7. inOrder1(root.right);
  8. }

2)非递归版本

算法思想:

1.节点不为空,入栈,访问左子树

2.节点为空但是栈不为空,出栈顶元素,打印,访问栈顶元素的右子树

3.栈为空并且节点为空,结束遍历

4.二叉树为空结束遍历

下面是中序遍历的非递归形式的代码实现:

  1. public void inOrder2(TreeNode root){
  2. Stack<TreeNode> stack = new Stack<>();
  3. TreeNode cur = root;
  4. while(!stack.empty()||cur!=null){
  5. if(cur!=null){
  6. stack.push(cur);
  7. cur=cur.left;
  8. }
  9. else{
  10. cur=stack.pop();
  11. System.out.print(cur.val+" ");
  12. cur=cur.right;
  13. }
  14. }
  15. }

运行结果:

三、后序遍历

后序遍历的顺序是左子树、右子树、根节点。

递归版本

  1. public void postOrder1(TreeNode root){
  2. if(root==null){
  3. return ;
  4. }
  5. postOrder1(root.left);
  6. postOrder1(root.right);
  7. System.out.println(root.val);
  8. }

非递归版本

后序遍历和前两个的遍历方法会有写不同,我们拿中序遍历来说,中序遍历是在遍历完左子树的时候,出根节点,打印根节点,访问右子树,但是后序遍历我们在访问左子树的之后需要访问右子树,在访问根节点,所以我们根节点不能在访问左子树之后出栈,需要继续访问右子树,当我们右子树访问完之后再出栈,所有我们就是必须需要

算法思路:

1.遍历左子树并且将左子树入栈

2.左子树为空的时候,访问右子树,有两种可能右子树为空:打印根节点,标记根节点,防止重复打印;树不为空,继续访问右子树的左子树,重复上诉过程

  1. public void postOrder2(TreeNode root){
  2. Stack<TreeNode> stack = new Stack<>();
  3. TreeNode cur = root;
  4. TreeNode prev = null;
  5. while(cur!=null||stack.empty()){
  6. while(cur!=null){
  7. stack.push(cur);
  8. cur=cur.left;
  9. }
  10. TreeNode top = stack.peek();
  11. if(top.right==null||top.right==prev){
  12. System.out.print(top.val+" ");
  13. prev=top;
  14. stack.pop();
  15. }
  16. else{
  17. cur=top.right;
  18. }
  19. }
  20. }

运行结果: 

 解释一下prev:

我们的二叉树当我们左子树遍历到D的时候我们的栈有A、B、D此时右子树不为空继续遍历栈中加入H元素此时栈顶元素为H,其右子树为空我们打印H,删除栈顶元素H,按照程序继续走我们现在栈顶元素是D,D的右子树不为空继续将H加入栈中此时会出现死循环,所以我们需要用一个prev表示上一次打印元素,防止重复进入栈。

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

闽ICP备14008679号