二叉树的四种遍历方式
二叉树的四种遍历方式:
- 二叉树的遍历(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+" ");}
讲完上面三种递归的方法,下面再给大家讲讲非递归是如何实现前中后序遍历的
还是一样,先看非递归前序遍历
- 首先申请一个新的栈,记为stack;
- 声明一个结点treeNode,让其指向node结点;
- 如果treeNode的不为空,将treeNode的值打印,并将treeNode入栈,然后让treeNode指向treeNode的右结点,
- 重复步骤3,直到treenode为空;
- 然后出栈,让treeNode指向treeNode的右孩子
- 重复步骤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;}}}
中序遍历非递归,在此不过多叙述具体步骤了,
具体过程:
- 申请一个新栈,记为stack,申请一个变量cur,初始时令treeNode为头节点;
- 先把treeNode节点压入栈中,对以treeNode节点为头的整棵子树来说,依次把整棵树的左子树压入栈中,即不断令treeNode=treeNode.leftChild,然后重复步骤2;
- 不断重复步骤2,直到发现cur为空,此时从stack中弹出一个节点记为treeNode,打印node的值,并让treeNode= treeNode.right,然后继续重复步骤2;
- 当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;}}}}
最后再给大家介绍一下层序遍历
具体步骤如下:
- 首先申请一个新的队列,记为queue;
- 将头结点head压入queue中;
- 每次从queue中出队,记为node,然后打印node值,如果node左孩子不为空,则将左孩子入队;如果node的右孩子不为空,则将右孩子入队;
- 重复步骤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);}}
二叉树的四种遍历方式相关推荐
- 二叉树的四种遍历方式——前序、中序、后序、层序遍历(递归+非递归实现)
如果N代表根节点,L代表根节点的左子树,R代表根节点的右子树,则根据遍历根节点的先后次序有以下遍历方式: 1. NLR:前序遍历(Preorder Traversal 亦称先序遍历)--访问根结点-- ...
- 二叉树的四种遍历方式(前序遍历、中序遍历、后序遍历、测层序遍历)
一.二叉树的遍历 遍历是数据结构中的常见的操作,把所有元素都访问一遍. 线性数据结构的遍历比较简单 ①.正序遍历 ②.逆序遍历 根据节点访问顺序的不同,二叉树的常见遍历方式用四种 ①.前序遍历(Pre ...
- 二叉树的四种遍历方式(递归和非递归双重实现)
写在前面:博主是一位普普通通的19届双非软工在读生,平时最大的爱好就是听听歌,逛逛B站.博主很喜欢的一句话花开堪折直须折,莫待无花空折枝:博主的理解是头一次为人,就应该做自己想做的事,做自己不后悔的事 ...
- 二叉树性质 四种遍历方式
二叉树基本概念: 每个结点最多有两棵子树,左子树和右子树(有左右之分) 性质: 二叉树的第n层上最多有2^(n-1)个元素 高度为h的二叉树最多有2^h-1个结点 设一棵二叉树的叶子节点数为a,度为2 ...
- 二叉树的四种遍历方法(前序遍历、中序遍历、后序遍历、层序遍历)有图有真相!!!
文章目录 二叉树的四种遍历方式 前序遍历(Preorder Traversal) 中序遍历(Inorder Traversal) 后序遍历(Postorder Traversal) 层序遍历(Leve ...
- 常用数据结构之二叉树及树的四种遍历方式
1.树 我们选择一种数据结构,不仅要能存储数据,而且要能体现数据之间的关系.目前数据主要有是三种关系一对一.一对多.多对多:之前我们讨论了线性表(数组.链表.栈.队列),其中的元素具有一对一的关系,通 ...
- c语言中二叉树中总结点,C语言二叉树的三种遍历方式的实现及原理
二叉树遍历分为三种:前序.中序.后序,其中序遍历最为重要.为啥叫这个名字?是根据根节点的顺序命名的. 比如上图正常的一个满节点,A:根节点.B:左节点.C:右节点,前序顺序是ABC(根节点排最先,然后 ...
- 二叉树的三种遍历方式(递归、非递归和Morris遍历)
二叉树的三种遍历方式(递归.非递归和Morris遍历) 原文:http://www.linuxidc.com/Linux/2015-08/122480.htm 二叉树遍历是二叉树的最基本的操作,其实现 ...
- 详解二叉树的三种遍历方式(递归、迭代、Morris算法)
详解二叉树的三种遍历方式(递归.迭代.Morris算法) 最重要的事情写在前面:遍历顺序不一定就是操作顺序!!! 递归解法 首先,一颗二叉树它的递归序列是一定的,导致其前中后序不同的原因只不过是访问节 ...
最新文章
- 设计模式 装饰者模式 带你重回传奇世界
- 【408预推免复习】计算机组成原理之计算机的运算方法
- 【干货】分享总结:MySQL数据一致性
- 接受你无法改变的事情 改变你可以改变的事情
- 阶段5 3.微服务项目【学成在线】_day04 页面静态化_09-freemarker基础-内建函数
- hdb3编码程序设计c语言,已知代码10000000001011,利用c语言程序编写AMI码跟HDB3码
- ps高低频磨皮详细教学
- word设置标题自动编号
- Java.MapReduce处理全国各省市疫情数据,上传Hadoop平台处理后的数据
- 家事:庆祝父亲60岁生日
- 如何用 canvas 画出分形图
- windows下使用route添加路由
- 国内外镜像下载合集(详细最终版)
- SQL 查询当前时间
- Firm C下的优化算法
- MySQL——Java 访问 MySQL 数据库
- 安捷伦示波器连接电脑
- 亚马逊儿童背包 CPSIA,CSPA邻苯二甲酸盐和镉 CPC测试
- 全球及中国建筑设计行业规划布局与十四五竞争现状分析报告2021版
- 【NPDP】大师级管理人物盘点:竞争战略之父-迈克尔·波特
热门文章
- Python数据结构学习笔记——树和图
- jmeter时间函数格林尼治时间_VB常用函数——时间函数和DateDiff函数
- 实验详解——DNS反向解析、DNS主服务器和从服务器的配置
- KILE退出调试模式时显示Encuntered an improper argument
- 如何设计一个优秀的向导式界面(Wizard)
- java.lang.OutOfMemoryError: Java heap space 错误及解决办法
- 单臂路由配置实验同一交换机上vlan间ping不通_【干货】什么是单臂路由?如何配置?...
- 公平锁非公平锁的实际使用_3. redisson源码公平锁之队列重排序
- iris数据_MAT之ELM:ELM实现鸢尾花(iris数据集)种类测试集预测识别正确率(better)结果对比...
- linux io映射,【原创】Linux 文件系统移植全解密以linux-2.6.35内核源码为例说明一下IO静态映射的过程...