二叉树的四种遍历方式:

  • 二叉树的遍历(traversing binary tree)是指从根结点出发,按照某种次序依次访问二叉树中所有的结点,使得每个结点被访问依次且仅被访问一次。
    四种遍历方式分别为:先序遍历、中序遍历、后序遍历、层序遍历。

遍历之前,我们首先介绍一下,如何创建一个二叉树,在这里用的是先建左树在建右树的方法,

首先要声明结点TreeNode类,代码如下:

public class TreeNode {public int data;public TreeNode leftChild;public TreeNode rightChild;public TreeNode(int data){this.data = data;}}

再来创建一颗二叉树:

/*** 构建二叉树* @param list   输入序列* @return*/public static TreeNode createBinaryTree(LinkedList<Integer> list){TreeNode node = null;if(list == null || list.isEmpty()){return null;}Integer data = list.removeFirst();if(data!=null){node = new TreeNode(data);node.leftChild = createBinaryTree(list);node.rightChild = createBinaryTree(list);}return node;}

接下来按照上面列的顺序一一讲解,

首先来看前序遍历,所谓的前序遍历就是先访问根节点,再访问左节点,最后访问右节点,

如上图所示,前序遍历结果为:ABDFECGHI

实现代码如下:

/*** 二叉树前序遍历   根-> 左-> 右* @param node    二叉树节点*/public static void preOrderTraveral(TreeNode node){if(node == null){return;}System.out.print(node.data+" ");preOrderTraveral(node.leftChild);preOrderTraveral(node.rightChild);}

再者就是中序遍历,所谓的中序遍历就是先访问左节点,再访问根节点,最后访问右节点,

如上图所示,中序遍历结果为:DBEFAGHCI

实现代码如下:

/*** 二叉树中序遍历   左-> 根-> 右* @param node   二叉树节点*/public static void inOrderTraveral(TreeNode node){if(node == null){return;}inOrderTraveral(node.leftChild);System.out.print(node.data+" ");inOrderTraveral(node.rightChild);}

最后就是后序遍历,所谓的后序遍历就是先访问左节点,再访问右节点,最后访问根节点。

如上图所示,后序遍历结果为:DEFBHGICA

实现代码如下:

/*** 二叉树后序遍历   左-> 右-> 根* @param node    二叉树节点*/public static void postOrderTraveral(TreeNode node){if(node == null){return;}postOrderTraveral(node.leftChild);postOrderTraveral(node.rightChild);System.out.print(node.data+" ");}

讲完上面三种递归的方法,下面再给大家讲讲非递归是如何实现前中后序遍历的

还是一样,先看非递归前序遍历

  1. 首先申请一个新的栈,记为stack;
  2. 声明一个结点treeNode,让其指向node结点;
  3. 如果treeNode的不为空,将treeNode的值打印,并将treeNode入栈,然后让treeNode指向treeNode的右结点,
  4. 重复步骤3,直到treenode为空;
  5. 然后出栈,让treeNode指向treeNode的右孩子
  6. 重复步骤3,直到stack为空.

实现代码如下:

public static void preOrderTraveralWithStack(TreeNode node){Stack<TreeNode> stack = new Stack<TreeNode>();TreeNode treeNode = node;while(treeNode!=null || !stack.isEmpty()){//迭代访问节点的左孩子,并入栈while(treeNode != null){System.out.print(treeNode.data+" ");stack.push(treeNode);treeNode = treeNode.leftChild;}//如果节点没有左孩子,则弹出栈顶节点,访问节点右孩子if(!stack.isEmpty()){treeNode = stack.pop();treeNode = treeNode.rightChild;}}}

中序遍历非递归,在此不过多叙述具体步骤了,

具体过程:

  1. 申请一个新栈,记为stack,申请一个变量cur,初始时令treeNode为头节点;
  2. 先把treeNode节点压入栈中,对以treeNode节点为头的整棵子树来说,依次把整棵树的左子树压入栈中,即不断令treeNode=treeNode.leftChild,然后重复步骤2;
  3. 不断重复步骤2,直到发现cur为空,此时从stack中弹出一个节点记为treeNode,打印node的值,并让treeNode= treeNode.right,然后继续重复步骤2;
  4. 当stack为空并且cur为空时结束。

public static void inOrderTraveralWithStack(TreeNode node){Stack<TreeNode> stack = new Stack<TreeNode>();TreeNode treeNode = node;while(treeNode!=null || !stack.isEmpty()){while(treeNode != null){stack.push(treeNode);treeNode = treeNode.leftChild;}if(!stack.isEmpty()){treeNode = stack.pop();System.out.print(treeNode.data+" ");treeNode = treeNode.rightChild;}}}

后序遍历非递归实现,后序遍历这里较前两者实现复杂一点,我们需要一个标记位来记忆我们此时节点上一个节点,具体看代码注释

public static void postOrderTraveralWithStack(TreeNode node){Stack<TreeNode> stack = new Stack<TreeNode>();TreeNode treeNode = node;TreeNode lastVisit = null;   //标记每次遍历最后一次访问的节点while(treeNode!=null || !stack.isEmpty()){//节点不为空,结点入栈,并且指向下一个左孩子while(treeNode!=null){stack.push(treeNode);treeNode = treeNode.leftChild;}//栈不为空if(!stack.isEmpty()){//出栈treeNode = stack.pop();/*** 这块就是判断treeNode是否有右孩子,* 如果没有输出treeNode.data,让lastVisit指向treeNode,并让treeNode为空* 如果有右孩子,将当前节点继续入栈,treeNode指向它的右孩子,继续重复循环*/if(treeNode.rightChild == null || treeNode.rightChild == lastVisit) {System.out.print(treeNode.data + " ");lastVisit = treeNode;treeNode  = null;}else{stack.push(treeNode);treeNode = treeNode.rightChild;}}}}

最后再给大家介绍一下层序遍历

具体步骤如下:

  1. 首先申请一个新的队列,记为queue;
  2. 将头结点head压入queue中;
  3. 每次从queue中出队,记为node,然后打印node值,如果node左孩子不为空,则将左孩子入队;如果node的右孩子不为空,则将右孩子入队;
  4. 重复步骤3,直到queue为空。

实现代码如下:

public static void levelOrder(TreeNode root){LinkedList<TreeNode> queue = new LinkedList<>();queue.add(root);while(!queue.isEmpty()){root = queue.pop();System.out.print(root.data+" ");if(root.leftChild!=null) queue.add(root.leftChild);if(root.rightChild!=null) queue.add(root.rightChild);}}

二叉树的四种遍历方式相关推荐

  1. 二叉树的四种遍历方式——前序、中序、后序、层序遍历(递归+非递归实现)

    如果N代表根节点,L代表根节点的左子树,R代表根节点的右子树,则根据遍历根节点的先后次序有以下遍历方式: 1. NLR:前序遍历(Preorder Traversal 亦称先序遍历)--访问根结点-- ...

  2. 二叉树的四种遍历方式(前序遍历、中序遍历、后序遍历、测层序遍历)

    一.二叉树的遍历 遍历是数据结构中的常见的操作,把所有元素都访问一遍. 线性数据结构的遍历比较简单 ①.正序遍历 ②.逆序遍历 根据节点访问顺序的不同,二叉树的常见遍历方式用四种 ①.前序遍历(Pre ...

  3. 二叉树的四种遍历方式(递归和非递归双重实现)

    写在前面:博主是一位普普通通的19届双非软工在读生,平时最大的爱好就是听听歌,逛逛B站.博主很喜欢的一句话花开堪折直须折,莫待无花空折枝:博主的理解是头一次为人,就应该做自己想做的事,做自己不后悔的事 ...

  4. 二叉树性质 四种遍历方式

    二叉树基本概念: 每个结点最多有两棵子树,左子树和右子树(有左右之分) 性质: 二叉树的第n层上最多有2^(n-1)个元素 高度为h的二叉树最多有2^h-1个结点 设一棵二叉树的叶子节点数为a,度为2 ...

  5. 二叉树的四种遍历方法(前序遍历、中序遍历、后序遍历、层序遍历)有图有真相!!!

    文章目录 二叉树的四种遍历方式 前序遍历(Preorder Traversal) 中序遍历(Inorder Traversal) 后序遍历(Postorder Traversal) 层序遍历(Leve ...

  6. 常用数据结构之二叉树及树的四种遍历方式

    1.树 我们选择一种数据结构,不仅要能存储数据,而且要能体现数据之间的关系.目前数据主要有是三种关系一对一.一对多.多对多:之前我们讨论了线性表(数组.链表.栈.队列),其中的元素具有一对一的关系,通 ...

  7. c语言中二叉树中总结点,C语言二叉树的三种遍历方式的实现及原理

    二叉树遍历分为三种:前序.中序.后序,其中序遍历最为重要.为啥叫这个名字?是根据根节点的顺序命名的. 比如上图正常的一个满节点,A:根节点.B:左节点.C:右节点,前序顺序是ABC(根节点排最先,然后 ...

  8. 二叉树的三种遍历方式(递归、非递归和Morris遍历)

    二叉树的三种遍历方式(递归.非递归和Morris遍历) 原文:http://www.linuxidc.com/Linux/2015-08/122480.htm 二叉树遍历是二叉树的最基本的操作,其实现 ...

  9. 详解二叉树的三种遍历方式(递归、迭代、Morris算法)

    详解二叉树的三种遍历方式(递归.迭代.Morris算法) 最重要的事情写在前面:遍历顺序不一定就是操作顺序!!! 递归解法 首先,一颗二叉树它的递归序列是一定的,导致其前中后序不同的原因只不过是访问节 ...

最新文章

  1. 设计模式 装饰者模式 带你重回传奇世界
  2. 【408预推免复习】计算机组成原理之计算机的运算方法
  3. 【干货】分享总结:MySQL数据一致性
  4. 接受你无法改变的事情 改变你可以改变的事情
  5. 阶段5 3.微服务项目【学成在线】_day04 页面静态化_09-freemarker基础-内建函数
  6. hdb3编码程序设计c语言,已知代码10000000001011,利用c语言程序编写AMI码跟HDB3码
  7. ps高低频磨皮详细教学
  8. word设置标题自动编号
  9. Java.MapReduce处理全国各省市疫情数据,上传Hadoop平台处理后的数据
  10. 家事:庆祝父亲60岁生日
  11. 如何用 canvas 画出分形图
  12. windows下使用route添加路由
  13. 国内外镜像下载合集(详细最终版)
  14. SQL 查询当前时间
  15. Firm C下的优化算法
  16. MySQL——Java 访问 MySQL 数据库
  17. 安捷伦示波器连接电脑
  18. 亚马逊儿童背包 CPSIA,CSPA邻苯二甲酸盐和镉 CPC测试
  19. 全球及中国建筑设计行业规划布局与十四五竞争现状分析报告2021版
  20. 【NPDP】大师级管理人物盘点:竞争战略之父-迈克尔·波特

热门文章

  1. Python数据结构学习笔记——树和图
  2. jmeter时间函数格林尼治时间_VB常用函数——时间函数和DateDiff函数
  3. 实验详解——DNS反向解析、DNS主服务器和从服务器的配置
  4. KILE退出调试模式时显示Encuntered an improper argument
  5. 如何设计一个优秀的向导式界面(Wizard)
  6. java.lang.OutOfMemoryError: Java heap space 错误及解决办法
  7. 单臂路由配置实验同一交换机上vlan间ping不通_【干货】什么是单臂路由?如何配置?...
  8. 公平锁非公平锁的实际使用_3. redisson源码公平锁之队列重排序
  9. iris数据_MAT之ELM:ELM实现鸢尾花(iris数据集)种类测试集预测识别正确率(better)结果对比...
  10. linux io映射,【原创】Linux 文件系统移植全解密以linux-2.6.35内核源码为例说明一下IO静态映射的过程...