二叉树的遍历是指从根结点出发,按照某种次序依次访问二叉树中所有结点,使得每个结点被访问一次且仅被访问一次。根据定义中的某种次序,二叉树的遍历方式主要分为前序遍历,中序遍历,后序遍历以及层序遍历。

前序遍历:若树为空空操作返回,否则先访问根结点,然后前序遍历左子树,再前序遍历右子树。

中序遍历:若树为空空操作返回,否则从树的根结点开始(注意并不是先访问根结点),中序遍历根结点的左子树,然后访问根结点,最后中序遍历右子树。

后序遍历:若树为空空操作返回,否则从树的根结点开始,后序遍历根结点的左子树,再后序遍历根结点的右子树,最后访问根结点。

1.前序遍历可以简单记为(根左右),中序遍历(左根右),后序遍历(左右根),哪个序遍历根就在哪个位置。从遍历方法的定义中可以看出,遍历的实现算法也可以采用递归。

实现代码:

package com.java.Search;
/** 二叉树的前序,中序,后序遍历* 以二叉排序树的特点创建一棵树* */public class SearchTest {public static void main(String[] args){BiTree bt=new BiTree();BiTree.insert(bt, 2);BiTree.insert(bt, 8);BiTree.insert(bt, 7);BiTree.insert(bt, 4);BiTree.insert(bt, 9);BiTree.insert(bt, 3);BiTree.insert(bt, 1);BiTree.insert(bt, 6);BiTree.insert(bt, 7);BiTree.insert(bt, 5);System.out.println(bt);System.out.print("前序遍历:");preorderTreverse(bt.root);System.out.print("中序遍历:");mediumTreverse(bt.root);System.out.print("后序遍历:");postorderTreverse(bt.root);}//前序遍历(根左右)public static void preorderTreverse(BiNode bt){if(bt==null){System.out.print("");}else{//访问根结点(访问定义为打印结点数值)System.out.print(bt.data);//前序遍历访问根结点的左子树preorderTreverse(bt.lchild);//前序遍历访问根结点的右子树preorderTreverse(bt.rchild);}}//中序遍历(左根右)public static void mediumTreverse(BiNode bt){if(bt==null){System.out.print("");}else{//中序遍历访问根结点的左子树mediumTreverse(bt.lchild);//访问根结点System.out.print(bt.data);//中序遍历访问根结点的右子树mediumTreverse(bt.rchild);}}//后序遍历(左右根)public static void postorderTreverse(BiNode bt){if(bt==null){System.out.print("");}else{//后序遍历根结点的左子树postorderTreverse(bt.lchild);//后序遍历根结点的右子树postorderTreverse(bt.rchild);//访问根结点System.out.print(bt.data);}}
}

上述代码中创建一棵二叉树是在前面二叉排序树的基础上创建的,也就是创建的这棵树满足二叉排序树的特点。然后对二叉排序树进行前序遍历,中序遍历以及后序遍历。

以前序遍历为例,首先判断是否为空,若为空,输出空字符串,否则先访问根结点,打印输出根结点值2,然后前序遍历访问根结点(设为root)的左子树,即调用preorderTreverse(root.lchild),传入的参数为根结点的左子树,同样开始执行preorderTreverse()的函数流程,先打印输出左子树的根结点值1,然后前序遍历值为1的结点(设为p)的左子树,即递归调用preorderTreverse(p.lchild),为空输出空字符串,然后调用preorderTreverse(p.rchild),也为空输出空字符串,到此访问root.lchild的调用结束,回到函数主体,调用preorderTreverse(root.rchild),传入的参数为根结点的右子树,开始右子树的递归调用。

2.层序遍历

层序遍历规则是若树为空,按空操作返回,否则从树的第一层(根结点)开始访问,从上而下逐层遍历,在同一层中,按照从左到右的顺序对结点逐个访问。

实现思路:

  • 首先判断根结点是否为空,若空,返回null;
  • 若非空,将根结点放入链表中;
  • 若链表非空,每次都检索并删除此链表的头,检索到此链表的头后赋值给headNode,并打印该结点的值;判断该结点是否有左右结点,依次加入链表的尾部;

实现代码:

//层序遍历--这里访问仍是打印该结点的值public static void layerTranverse(BiTree bt){if(bt.root==null){System.out.println("null");}else{Queue<BiNode> q=new LinkedList<BiNode>();q.add(bt.root);while(!q.isEmpty()){//poll()-->检索并删除此链表的头(第一个元素)。BiNode headNode=q.poll();System.out.print(headNode.data);if(headNode.lchild!=null){q.add(headNode.lchild);}if(headNode.rchild!=null){q.add(headNode.rchild);}}}
}

3.推导遍历结果

已知前序遍历和中序遍历序列,可以唯一确定一棵二叉树;已知后序遍历和中序遍历序列,可以唯一确定一棵二叉树序列。

3.1 由前序遍历和中序遍历序列,推导后序遍历结果

实现思路:

  1. 由前序遍历序列确定树的根结点,根结点为前序遍历序列的第一个结点;
  2. 由1得到的根结点及中序遍历序列确定根结点的左子树和右子树的结点有哪些,确立的这些结点序列分别为根结点左子树和右子树的中序遍历结果;
  3. 找到前序遍历序列中对应的根结点的左子树和右子树的前序遍历结果,至此确定了根结点的左子树和右子树的前序遍历序列以及中序遍历序列;
  4. 递归调用,构建根结点的左子树和右子树;

实现代码:

//根据前序遍历和中序遍历确定二叉树的后序遍历
//一.首先根据前序遍历和中序遍历确定二叉树
public static BiNode initTree(int[] preOrder,int start1,int end1,int[] mediumOrder,int start2,int end2){if (start1>end1 || start2>end2){return null;}//1.确立根结点-->根结点为前序遍历的第一个结点int rootData=preOrder[start1];BiNode headNode=new BiNode(rootData);//2.根据中序遍历结果确立根结点的左子树和右子树-->左子树和右子树结点有哪些//中序遍历结果根结点左右的为左子树和右子树结点-->先要确立根结点在中序遍历结果中的索引位置//方法不要写死,后面要递归调用 int rootIndex=findIndexInArray(mediumOrder,rootData,start2,end2);//3.确立根结点左子树的结点个数int offset=rootIndex-start2-1; //4.构建头结点的左右子树BiNode ltree=initTree(preOrder,start1+1,start1+offset+1,mediumOrder,start2,start2+offset);BiNode rtree=initTree(preOrder,start1+offset+2,end1,mediumOrder,rootIndex+1,end2);headNode.lchild=ltree;headNode.rchild=rtree;return headNode;
}

3.2 由后序遍历和中序遍历序列,推导前序遍历结果

实现思路:

  1. 由后序遍历序列确定树的根结点,根结点为后序遍历的最后一个结点;
  2. 由1得到的根结点及中序遍历序列确定根结点的左子树和右子树的结点有哪些,确立的这些结点序列分别为根结点左子树和右子树的中序遍历结果;
  3. 找到后序遍历序列中对应的根结点的左子树和右子树的后序遍历结果,至此确定了根结点的左子树和右子树的后序遍历序列以及中序遍历序列;
  4. 递归调用,构建根结点的左子树和右子树;

实现代码:

public static BiNode initTree2(int[] postOrder,int start1,int end1,int[] mediumOrder,int start2,int end2){if(start1>end1 || start2>end2){return null;}int rootData=postOrder[end1];BiNode headNode=new BiNode(rootData);int rootIndex=findIndexInArray(mediumOrder,rootData,start2,end2);int offset=end2-rootIndex;BiNode ltree=initTree2(postOrder,start1,end1-offset-1,mediumOrder,start2,rootIndex-1);BiNode rtree=initTree2(postOrder,end1-offset,end1-1,mediumOrder,rootIndex+1,end2);headNode.lchild=ltree;headNode.rchild=rtree;return headNode;
}

4.完整代码

package com.java.Search;import java.util.LinkedList;
import java.util.Queue;/** 二叉树的前序,中序,后序遍历,层序遍历 * 以二叉排序树的特点创建一棵树* */
public class SearchTest {public static void main(String[] args){BiTree bt=new BiTree();BiTree.insert(bt, 2);BiTree.insert(bt, 8);BiTree.insert(bt, 7);BiTree.insert(bt, 4);BiTree.insert(bt, 9);BiTree.insert(bt, 3);BiTree.insert(bt, 1);BiTree.insert(bt, 6);BiTree.insert(bt, 5);//System.out.println(bt);System.out.print("前序遍历:");preorderTreverse(bt.root);System.out.print("中序遍历:");mediumTreverse(bt.root);System.out.print("后序遍历:");postorderTreverse(bt.root);//layerTranverse(bt);int[] preOrder={2,1,8,7,4,3,6,5,9};int[] mediumOrder={1,2,3,4,5,6,7,8,9};BiNode tree=initTree(preOrder,0,preOrder.length-1,mediumOrder,0,mediumOrder.length-1);System.out.println("");System.out.println("由前序遍历和中序遍历得到的树为:"+tree);System.out.print("后序遍历的树为:");postorderTreverse(tree);int[] postOrder={1,3,5,6,4,7,9,8,2};BiNode tree2=initTree2(postOrder,0,postOrder.length-1,mediumOrder,0,mediumOrder.length-1);System.out.println("");System.out.println("由后序遍历和中序遍历得到的树为:"+tree2);System.out.print("前序遍历的树为:");preorderTreverse(tree2);}//前序遍历(根左右)public static void preorderTreverse(BiNode bt){if(bt==null){System.out.print("");}else{//访问根结点(访问定义为打印结点数值)System.out.print(bt.data);//前序遍历访问根结点的左子树preorderTreverse(bt.lchild);//前序遍历访问根结点的右子树preorderTreverse(bt.rchild);}}//中序遍历(左根右)public static void mediumTreverse(BiNode bt){if(bt==null){System.out.print("");}else{//中序遍历访问根结点的左子树mediumTreverse(bt.lchild);//访问根结点System.out.print(bt.data);//中序遍历访问根结点的右子树mediumTreverse(bt.rchild);}}//后序遍历(左右根)public static void postorderTreverse(BiNode bt){if(bt==null){System.out.print("");}else{//后序遍历根结点的左子树postorderTreverse(bt.lchild);//后序遍历根结点的右子树postorderTreverse(bt.rchild);//访问根结点System.out.print(bt.data);}}//层序遍历--这里访问仍是打印该结点的值public static void layerTranverse(BiTree bt){if(bt.root==null){System.out.println("null");}else{Queue<BiNode> q=new LinkedList<BiNode>();q.add(bt.root);while(!q.isEmpty()){//poll()-->检索并删除此链表的头(第一个元素)。BiNode headNode=q.poll();System.out.print(headNode.data);if(headNode.lchild!=null){q.add(headNode.lchild);}if(headNode.rchild!=null){q.add(headNode.rchild);}}}}//由后序遍历和中序遍历确定二叉树的前序遍历public static BiNode initTree2(int[] postOrder,int start1,int end1,int[] mediumOrder,int start2,int end2){if(start1>end1 || start2>end2){return null;}int rootData=postOrder[end1];BiNode headNode=new BiNode(rootData);int rootIndex=findIndexInArray(mediumOrder,rootData,start2,end2);int offset=end2-rootIndex;BiNode ltree=initTree2(postOrder,start1,end1-offset-1,mediumOrder,start2,rootIndex-1);BiNode rtree=initTree2(postOrder,end1-offset,end1-1,mediumOrder,rootIndex+1,end2);headNode.lchild=ltree;headNode.rchild=rtree;return headNode;}//根据前序遍历和中序遍历确定二叉树的后序遍历//一.首先根据前序遍历和中序遍历确定二叉树public static BiNode initTree(int[] preOrder,int start1,int end1,int[] mediumOrder,int start2,int end2){if (start1>end1 || start2>end2){return null;}//1.确立根结点-->根结点为前序遍历的第一个结点int rootData=preOrder[start1];BiNode headNode=new BiNode(rootData);//2.根据中序遍历结果确立根结点的左子树和右子树-->左子树和右子树结点有哪些//中序遍历结果根结点左右的为左子树和右子树结点-->先要确立根结点在中序遍历结果中的索引位置//方法不要写死,后面要递归调用 int rootIndex=findIndexInArray(mediumOrder,rootData,start2,end2);//3.确立根结点左子树的结点个数int offset=rootIndex-start2-1; //4.构建头结点的左右子树BiNode ltree=initTree(preOrder,start1+1,start1+offset+1,mediumOrder,start2,start2+offset);BiNode rtree=initTree(preOrder,start1+offset+2,end1,mediumOrder,rootIndex+1,end2);headNode.lchild=ltree;headNode.rchild=rtree;return headNode;}//确立根结点在中序遍历结果中的索引位置public static int findIndexInArray(int[] a,int x,int begin,int end){int index=0;for(int i=begin;i<=end;i++){if(a[i]==x){index=i;}}return index;}
}

运行结果:

前序遍历:218743659中序遍历:123456789后序遍历:135647982
由前序遍历和中序遍历得到的树为:BiNode [data=2, lchild=BiNode [data=1, lchild=null, rchild=null], rchild=BiNode [data=8, lchild=BiNode [data=7, lchild=BiNode [data=4, lchild=BiNode [data=3, lchild=null, rchild=null], rchild=BiNode [data=6, lchild=BiNode [data=5, lchild=null, rchild=null], rchild=null]], rchild=null], rchild=BiNode [data=9, lchild=null, rchild=null]]]
后序遍历的树为:135647982
由后序遍历和中序遍历得到的树为:BiNode [data=2, lchild=BiNode [data=1, lchild=null, rchild=null], rchild=BiNode [data=8, lchild=BiNode [data=7, lchild=BiNode [data=4, lchild=BiNode [data=3, lchild=null, rchild=null], rchild=BiNode [data=6, lchild=BiNode [data=5, lchild=null, rchild=null], rchild=null]], rchild=null], rchild=BiNode [data=9, lchild=null, rchild=null]]]
前序遍历的树为:218743659

转载于:https://www.cnblogs.com/bluetree2/p/10301204.html

二叉树的几种遍历方法相关推荐

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

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

  2. 二叉树的四种遍历方法:前序、中序、后序、层次

    前/中/后序遍历也可分别称为前/中/后根遍历 #include <iostream> using namespace std;//二叉树的链式存储的结点 typedef struct Bi ...

  3. 二叉树的四种遍历方式

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

  4. 二叉树的三种遍历(递归与非递归) + 层次遍历

    <转载于  >>> > 二叉树是一种非常重要的数据结构,很多其他数据机构都是基于二叉树的基础演变过来的.二叉树有前.中.后三种遍历方式,因为树的本身就是用递归定义的,因此 ...

  5. 打印完全二叉树java_java 完全二叉树的构建与四种遍历方法示例

    本来就是基础知识,不能丢的太干净,今天竟然花了那么长的时间才写出来,记一下. 有如下的一颗完全二叉树: 先序遍历结果应该为:1  2  4  5  3  6  7 中序遍历结果应该为:4  2  5  ...

  6. 二叉树的五种遍历方式

    目录 1.前序遍历 (1)递归实现前序遍历 (2)非递归实现前序遍历 2.中序遍历 (1)递归实现中序遍历 (2)非递归实现中序遍历 3.后序遍历 (1)递归实现后序遍历 (2)非递归实现后序遍历 4 ...

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

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

  8. java从1到9构建完全二叉树_Java完全二叉树的创建与四种遍历方法分析

    Java完全二叉树的创建与四种遍历方法分析 发布时间:2020-10-01 11:58:56 来源:脚本之家 阅读:87 作者:泡0沫 本文实例讲述了Java完全二叉树的创建与四种遍历方法.分享给大家 ...

  9. 【Python算法系列十一】二叉树的3种遍历方式

    二叉树的遍历是指从根结点出发,按照某种次序依次访问二叉树中所有结点,使得每个结点被访问一次且仅被访问一次. 遍历二叉树的方法主要分 3 种:先序遍历.中序遍历和后序遍历: 先序遍历指最先遍历节点本身, ...

最新文章

  1. 前端技术周刊 2018-03-02
  2. C#实现web信息自动抓取
  3. mysql优化之连接优化
  4. div自动滚动_从手机滚动丢帧问题,学习浏览器合成与渲染层优化
  5. 5、扩展骨架文件内容
  6. Linux 端口占用情况查看
  7. Cell插件在J2EE系统中的应用
  8. win7显示时钟与服务器同步失败,win7时间同步出错_Win7电脑时间同步出错怎么办...
  9. 无损连接和保持依赖性(有脑就行,尽量说人话版本)
  10. 《非暴力沟通》---第二章(是什么蒙蔽了爱?)读书笔记
  11. javaScript内存溢出vue-cli3解决方案
  12. python图像拉伸
  13. kindlefire刷安卓系统_测试kindle fire 刷安卓4系统用手机GPS模块导航
  14. 虚拟局域网软件开源_局域网视频会议行业专业术语你知道哪些?
  15. 【2022-01-06】验证码合集
  16. 利用BP神经网络进行公路客运货运量的预测
  17. Spring Boot重定向
  18. Android 修改Preferences样式
  19. 吴恩达团队2022机器学习课程,来啦
  20. 盘点 市面上超火的7款界面设计软件

热门文章

  1. iconpath 微信小程序_微信小程序开发(全局配置文件)
  2. js判断对象为空_在 JavaScript 中如何检查对象为空
  3. python制作查询工具发给别人使用_用Python制作天气查询软件
  4. 银行家算法 计算机操作系统,计算机操作系统 银行家算法.doc
  5. 北师大高级程序c语言,北师大《高级程序设计C语言》.doc
  6. linux设置默认终端模拟器,ubuntu终端默认设置_在Ubuntu Linux上设置默认终端模拟器...
  7. python语音分割_Python 牺牲性能以提升程序员的工作效率
  8. freertos 编译c++失败_FreeRTOS的初次见面
  9. go去掉最后一个字符_Go:字符串操作
  10. c语言寻找公共字符串,C语言查找两个字符串中的最大公共子串