java先序中序后序遍历二叉树_二叉树的前序中序后续

java先序中序后序遍历二叉树_二叉树的前序中序后续1.前序遍历    前序遍历(DLR,lchild,data,rchild),是二叉树遍历的一种,也叫做先根遍历、先序遍历、前序周游,可记做根左右。前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树。若二叉树为空则结束返回,否则:(1)访问根结点。(2)前序遍历左子树。(3…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

1.前序遍历

    前序遍历(DLR,lchild,data,rchild),是二叉树遍历的一种,也叫做先根遍历、先序遍历、前序周游,可记做根左右。前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。

前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问
根结点,然后遍历左子树,最后遍历右子树。

二叉树为空则结束返回,否则:
(1)访问根结点。
(2)前序遍历左子树
(3)前序遍历右子树 。

前序遍历
前序遍历
需要注意的是:遍历左右子树时仍然采用前序遍历方法。
如右图所示
二叉树
前序遍历结果:ABDECF
已知后序遍历和中序遍历,就能确定前序遍历。

    其实在遍历二叉树的时候有三次遍历, 比如前序遍历:A->B->D->D(D左子节点并返回到D)->D(D右子节点并返回到D)->B->E->E(左)->E(右)->->B->A->C->F->F(左)->F(右)->C->C(右),所以可以用栈结构,把遍历到的节点压进栈,没子节点时再出栈。也可以用递归的方式,递归的输出当前节点,然后递归的输出左子节点,最后递归的输出右子节点。直接看代码更能理解:

package test;
//前序遍历的递归实现与非递归实现
import java.util.Stack;
public class Test 
{
	public static void main(String[] args)
	{
		TreeNode[] node = new TreeNode[10];//以数组形式生成一棵完全二叉树
		for(int i = 0; i < 10; i++)
		{
			node[i] = new TreeNode(i);
		}
		for(int i = 0; i < 10; i++)
		{
			if(i*2+1 < 10)
				node[i].left = node[i*2+1];
			if(i*2+2 < 10)
				node[i].right = node[i*2+2];
		}
		
		preOrderRe(node[0]);
	}
	
	public static void preOrderRe(TreeNode biTree)
	{//递归实现
		System.out.println(biTree.value);
		TreeNode leftTree = biTree.left;
		if(leftTree != null)
		{
			preOrderRe(leftTree);
		}
		TreeNode rightTree = biTree.right;
		if(rightTree != null)
		{
			preOrderRe(rightTree);
		}
	}
	
	public static void preOrder(TreeNode biTree)
	{//非递归实现
		Stack<TreeNode> stack = new Stack<TreeNode>();
		while(biTree != null || !stack.isEmpty())
		{
			while(biTree != null)
			{
				System.out.println(biTree.value);
				stack.push(biTree);
				biTree = biTree.left;
			}
			if(!stack.isEmpty())
			{
				biTree = stack.pop();
				biTree = biTree.right;
			}
		}
	}
}

class TreeNode//节点结构
{
	int value;
	TreeNode left;
	TreeNode right;
	
	TreeNode(int value)
	{
		this.value = value;
	}
}



2.中序遍历

中序遍历(LDR)是
二叉树遍历的一种,也叫做
中根遍历、中序周游。在二叉树中,先左后根再右。巧记:左根右。
中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树

二叉树为空则结束返回,
否则:

  

java先序中序后序遍历二叉树_二叉树的前序中序后续

(1)中序遍历左子树

(2)访问根结点
(3)中序遍历右子树
如右图所示
二叉树
中序遍历结果:DBEAFC

import java.util.Stack;public class Test {	public static void main(String[] args)	{		TreeNode[] node = new TreeNode[10];//以数组形式生成一棵完全二叉树		for(int i = 0; i < 10; i++)		{			node[i] = new TreeNode(i);		}		for(int i = 0; i < 10; i++)		{			if(i*2+1 < 10)				node[i].left = node[i*2+1];			if(i*2+2 < 10)				node[i].right = node[i*2+2];		}				midOrderRe(node[0]);		System.out.println();		midOrder(node[0]);	}		public static void midOrderRe(TreeNode biTree)	{//中序遍历递归实现		if(biTree == null)			return;		else		{			midOrderRe(biTree.left);			System.out.println(biTree.value);			midOrderRe(biTree.right);		}	}			public static void midOrder(TreeNode biTree)	{//中序遍历费递归实现		Stack<TreeNode> stack = new Stack<TreeNode>();		while(biTree != null || !stack.isEmpty())		{			while(biTree != null)			{				stack.push(biTree);				biTree = biTree.left;			}			if(!stack.isEmpty())			{				biTree = stack.pop();				System.out.println(biTree.value);				biTree = biTree.right;			}		}	}}class TreeNode//节点结构{	int value;	TreeNode left;	TreeNode right;		TreeNode(int value)	{		this.value = value;	}}

3.后序遍历(难点)

后序遍历(LRD)是
二叉树遍历的一种,也叫做
后根遍历、后序周游,可记做左右根。后序遍历有
递归算法和非递归算法两种。在二叉树中,先左后右再根。巧记:左右根。
后序遍历首先遍历左子树,然后遍历右子树,最后访问根结点,在遍历左、右子树时,仍然先遍历左子树,然后遍历右子树,最后遍历根结点。即:

二叉树为空则结束返回,
否则:

java先序中序后序遍历二叉树_二叉树的前序中序后续

(1)后序遍历左子树

(2)后序遍历右子树
(3)访问根结点
如右图所示
二叉树
后序遍历结果:DEBFCA
已知前序遍历和中序遍历,就能确定后序遍历。

算法核心思想:

    首先要搞清楚先序、中序、后序的非递归算法共同之处:用栈来保存先前走过的路径,以便可以在访问完子树后,可以利用栈中的信息,回退到当前节点的双亲节点,进行下一步操作。

    后序遍历的非递归算法是三种顺序中最复杂的,原因在于,后序遍历是先访问左、右子树,再访问根节点,而在非递归算法中,利用栈回退到时,并不知道是从左子树回退到根节点,还是从右子树回退到根节点,如果从左子树回退到根节点,此时就应该去访问右子树,而如果从右子树回退到根节点,此时就应该访问根节点。所以相比前序和后序,必须得在压栈时添加信息,以便在退栈时可以知道是从左子树返回,还是从右子树返回进而决定下一步的操作。


import java.util.Stack;public class Test {	public static void main(String[] args)	{		TreeNode[] node = new TreeNode[10];//以数组形式生成一棵完全二叉树		for(int i = 0; i < 10; i++)		{			node[i] = new TreeNode(i);		}		for(int i = 0; i < 10; i++)		{			if(i*2+1 < 10)				node[i].left = node[i*2+1];			if(i*2+2 < 10)				node[i].right = node[i*2+2];		}				postOrderRe(node[0]);		System.out.println("***");		postOrder(node[0]);	}				public static void postOrderRe(TreeNode biTree)	{//后序遍历递归实现		if(biTree == null)			return;		else		{			postOrderRe(biTree.left);			postOrderRe(biTree.right);			System.out.println(biTree.value);		}	}		public static void postOrder(TreeNode biTree)	{//后序遍历非递归实现		int left = 1;//在辅助栈里表示左节点		int right = 2;//在辅助栈里表示右节点		Stack<TreeNode> stack = new Stack<TreeNode>();		Stack<Integer> stack2 = new Stack<Integer>();//辅助栈,用来判断子节点返回父节点时处于左节点还是右节点。				while(biTree != null || !stack.empty())		{			while(biTree != null)			{//将节点压入栈1,并在栈2将节点标记为左节点				stack.push(biTree);				stack2.push(left);				biTree = biTree.left;			}						while(!stack.empty() && stack2.peek() == right)			{//如果是从右子节点返回父节点,则任务完成,将两个栈的栈顶弹出				stack2.pop();				System.out.println(stack.pop().value);			}						if(!stack.empty() && stack2.peek() == left)			{//如果是从左子节点返回父节点,则将标记改为右子节点				stack2.pop();				stack2.push(right);				biTree = stack.peek().right;			}						}	}}class TreeNode//节点结构{	int value;	TreeNode left;	TreeNode right;		TreeNode(int value)	{		this.value = value;	}}

4.层次遍历

    与树的前中后序遍历的DFS思想不同,层次遍历用到的是BFS思想。一般DFS用递归去实现(也可以用栈实现),BFS需要用队列去实现。

层次遍历的步骤是:

    1.对于不为空的结点,先把该结点加入到队列中

    2.从队中拿出结点,如果该结点的左右结点不为空,就分别把左右结点加入到队列中

    3.重复以上操作直到队列为空

	public static void levelOrder(TreeNode biTree)
	{//层次遍历
		if(biTree == null)
			return;
		LinkedList<TreeNode> list = new LinkedList<TreeNode>();
		list.add(biTree);
		TreeNode currentNode;
		while(!list.isEmpty())
		{
			currentNode = list.poll();
			System.out.println(currentNode.value);
			if(currentNode.left != null)
				list.add(currentNode.left);
			if(currentNode.right != null)
				list.add(currentNode.right);
		}
	}

先序遍历特点:第一个值是根节点

中序遍历特点:根节点左边都是左子树,右边都是右子树

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/193827.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 解决树莓派IOError: [Errno Invalid sample rate] -9997 采样率16K错误

    解决树莓派IOError: [Errno Invalid sample rate] -9997 采样率16K错误树莓派在基于pyaudio录音的时候会提示如上错误,这主要是使用的树莓派声卡不支持当前的采用率,没关系,其实在alsa架构下我们可以通过声卡的插件实现转换。在树莓派下家目录创建一个声卡隐藏配置文件 .asoundrc。特别不要在你的pyaudio里面设置打开声卡的编号因为下面的配置以及配置了pcm.!default{typehwcard1}ctl.!default{…

    2022年10月16日
  • Matlab由三维散点绘制三维曲面(含等高线,剖面图)「建议收藏」

    Matlab由三维散点绘制三维曲面(含等高线,剖面图)「建议收藏」绘图描述:由若干个给定的三维散点(x,y,z)绘制一个三维的曲面,具体的效果如图:伪彩图:等高线:三维曲面(深色):三维曲面(浅色)+等高线:剖面图:Matlab程序如下:其中A就是我们散点的数据矩阵A=[173.699116.986-409.863130.39108.312-388.571187.8261…

    2022年10月11日
  • oracle数据库心得体会_oracle基础知识入门

    oracle数据库心得体会_oracle基础知识入门Oracle的体系太庞大了,对于初学者来说,难免会有些无从下手的感觉,什么都想学,结果什么都学不好,所以把学习经验共享一下,希望让刚刚入门的人对oracle有一个总体的认识,少走一些弯路。  一、定位  oracle分两大块,一块是开发,一块是管理。开发主要是写写存储过程、触发器什么的,还有就是用Oracle的Develop工具做form。有点类似于程序员,需要有较强的逻辑思维和创造能力,

  • 解决SqlTransaction用尽的问题

    解决SqlTransaction用尽的问题解决SqlTransaction用尽的问题有时候程序处理的数据量比较小时,四平八稳,一切安然无恙,但数据量一大,原先潜伏的问题就暴露无遗了。我做的一个项目,是负责一个厂的考勤的。厂里有员工1000多号人。按每人每天打4次卡,一个月30天,则产生的考勤记录数目为1000*4*30=120,000条。在处理这些记录时,我采用的办法是先生成SQL语句,然后执行这些SQL语句:Sql…

  • c++ 11 list转set「建议收藏」

    c++ 11 list转set「建议收藏」list<int> li; for(inti=0;i<100;i++){ li.push_back(i); } for(inti=0;i<100;i++){ li.push_back(i); } unordered_set<int> uset(li.begin(),li.end());//用list去初始化s…

  • kill命令杀死所有进程_ubuntu杀死进程命令

    kill命令杀死所有进程_ubuntu杀死进程命令常规篇: 首先,用ps查看进程,方法如下:$ps-ef……smx      1822    1 011:38?       00:00:49gnome-terminalsmx      1823 1822 011:38?       00:00:00gnome-pty-helpersmx      1824 1822 011:38

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号