Java语言实现非递归实现树的前中后序遍历总结

 更新时间:2019年01月03日 14:35:04   作者:sdr_zd  
今天小编就为大家分享一篇关于Java语言实现非递归实现树的前中后序遍历总结,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

前言

三种遍历的递归写法都很好写,所以总结一下非递归写法。

先贴一张图复习一下三种遍历方式就进入正文啦~

【注:本文所有代码实现中树的结点定义如下:

public class Node {
  int val;
  Node left;
  Node right;
  Node parent;
  Node() {}
  Node(int val) {
    this.val = val;
  }
}

1.前序遍历

实现思路:

前序遍历的顺序是:根结点 -> 左孩子 -> 右孩子

借助一个栈结构先将根结点压入栈,然后循环每次取出栈顶元素,直到栈为空。如果当前结点有右孩子就先将右孩子压入栈中,如果当前结点有左孩子就将左孩子压入栈中,这里注意顺序,因为栈的结构是先进后出的,为了保证先遍历到左孩子就应该后压左孩子~

代码实现:

【代码使用直接输出的方式打印中序遍历结果,也可以放入一个list中存储~】

public void preOrder(Node head) {
    System.out.println("pre-order:");
    if(head != null) {
      Stack<Node> stack = new Stack<>();
      stack.push(head);
      while(!stack.isEmpty()) {
        head = stack.pop();
        System.out.print(head.val + " ");
        if (head.right != null)
          stack.push(head.right);
        if (head.left != null)
          stack.push(head.left);
      }
    }
  }

2.中序遍历

实现思路:

中序遍历的顺序:左孩子 -> 根结点 -> 右孩子

借助栈结构,将当前结点的左孩子依次入栈直到没有左孩子了就弹出栈顶元素并打印,如果弹出的结点有右孩子就将右孩子的左边界依次入栈,循环…

比如文章开始的那个图中,先将A,B,D依次入栈,此时栈顶元素是D,弹出并打印,D结点有右孩子,将D的右孩子的左边界依次入栈,压入结点G,结点G没有左孩子所以弹出并打印G,此时栈顶元素是B,循环…直到栈中为空且当前结点为空时遍历结束。

代码实现:

public static void inOrderTraverse(Node head) {
    System.out.println("in-order:");
    if(head != null) {
      Stack<Node> stack = new Stack<>();
      while(!stack.isEmpty() || head != null) {
        if(head != null) {
          // 当前节点不为空, 将自己压进栈并将自己的左孩子作为当前节点(压入左边界)
          stack.push(head);
          head = head.left;
        }else {
          // 当前节点为空(没有左孩子了), 将栈顶元素弹出作为当前节点, 并将当前节点的右孩子压进栈
          head = stack.pop();
          System.out.print(head.val + " ");
          head = head.right;
        }
      }
    }
  }

3.后序遍历

实现思路:

后序遍历的顺序:左孩子 -> 右孩子 -> 根结点

仔细想一下,打印每个结点需要访问根结点三次,先从根结点开始找到左孩子,返回再找到右孩子,再返回到根结点,需要访问根结点三次,直接按照当前顺序进行遍历不知如何下手,那么我们可以换一个角度去考虑。

栈结构是先进后出的,那我们不妨借助一个栈先存储 根结点 -> 右孩子 -> 左孩子 的结果,再将其依次弹出就是后序遍历的顺序了。

那实现 根结点 -> 右孩子 -> 左孩子 的方法就很简单了,回忆一下刚才说的前序遍历的方式,前序遍历是先要左孩子,就后压入左孩子,反之,将前序遍历的逻辑改写为:弹出每个栈顶结点作为当前结点并存储到一个辅助栈中,如果当前结点有左孩子就先压入左孩子,如果有右孩子就后压入右孩子,每次取栈顶弹出到辅助栈中。最后将得到的辅助栈中元素依次弹出得到的就是后序遍历的结果。

代码实现:

public static void posOrderTraverse(Node head) {
    System.out.println("pos-order");
    if(head != null) {
      Stack<Node> stack1 = new Stack<>();
      Stack<Node> stack2 = new Stack<>();   // 辅助栈,存储 根 -> 右 -> 左 的结果
      stack1.push(head);
      while(!stack1.isEmpty()) {
        head = stack1.pop();
        stack2.push(head);
        // 有左孩子就先压入左孩子
        if(head.left != null)
          stack1.push(head.left);
        // 有右孩子就后压入右孩子
        if(head.right != null)
          stack1.push(head.right);
      }
      // 逆序打印 根 -> 右 -> 左 的结果,就是后序遍历的结果
      while(!stack2.isEmpty())
        System.out.print(stack2.pop().val + " ");
    }
  }

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。如果你想了解更多相关内容请查看下面相关链接

相关文章

  • Java 堆内存与栈内存详细介绍

    Java 堆内存与栈内存详细介绍

    这篇文章主要介绍了Java 堆内存与栈内存详细介绍的相关资料,这里对java 的堆内存和栈内存进行了详细的分析,需要的朋友可以参考下
    2016-11-11
  • 如何利用JAVA实现走迷宫程序

    如何利用JAVA实现走迷宫程序

    最近经常在机房看同学在玩一个走迷宫的游戏,比较有趣,自己也用java实现了一个,这篇文章主要给大家介绍了关于如何利用JAVA实现走迷宫程序的相关资料,需要的朋友可以参考下
    2021-06-06
  • SpringBoot整合EasyCaptcha实现图形验证码功能

    SpringBoot整合EasyCaptcha实现图形验证码功能

    这篇文章主要介绍了SpringBoot整合EasyCaptcha实现图形验证码功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2024-02-02
  • Java如何简单快速入门JWT(token生成与验证)

    Java如何简单快速入门JWT(token生成与验证)

    这篇文章主要给大家介绍了关于Java如何简单快速入门JWT(token生成与验证)的相关资料,JWT是一个加密的字符串,JWT传输的信息经过了数字签名,因此传输的信息可以被验证和信任,需要的朋友可以参考下
    2023-12-12
  • Java跨域问题的几种后端解决方式举例详解

    Java跨域问题的几种后端解决方式举例详解

    跨域,是指浏览器不能执行其他网站的脚本,它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制,这篇文章主要给大家介绍了关于Java跨域问题的几种后端解决方式的相关资料,需要的朋友可以参考下
    2023-11-11
  • java中的IO流

    java中的IO流

    这篇文章主要介绍了java中的IO流的相关资料,需要的朋友可以参考下文
    2021-08-08
  • Java的Struts框架简介与环境配置教程

    Java的Struts框架简介与环境配置教程

    这篇文章主要介绍了Java的Struts框架与其环境配置教程,Struts框架是Java注明的SSH三大web开发框架之一,需要的朋友可以参考下
    2015-11-11
  • idea如何自定义代码模板

    idea如何自定义代码模板

    这篇文章主要介绍了idea如何自定义代码模板问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • 详解如何使用SpringBoot封装Excel生成器

    详解如何使用SpringBoot封装Excel生成器

    在软件开发过程中,经常需要生成Excel文件来导出数据或者生成报表,为了简化开发流程和提高代码的可维护性,我们可以使用Spring Boot封装Excel生成器,本文将介绍如何使用Spring Boot封装Excel生成器,并提供一些示例代码来说明其用法和功能
    2023-06-06
  • Hadoop Combiner使用方法详解

    Hadoop Combiner使用方法详解

    这篇文章主要介绍了 Hadoop Combiner使用方法详解的相关资料,希望通过本文能帮助到大家让大家理解掌握这部分内容,需要的朋友可以参考下
    2017-10-10

最新评论