数据结构——二叉树的先中后序遍历

2023-05-16

——本节内容为Bilibili王道考研《数据结构》P43~P45视频内容笔记。


目录

一、二叉树的先中后序遍历

1.先中后序遍历

2.举例

 3.先中后序遍历和前中后缀的关系

4.代码实现

5.求遍历序列

6.应用:求树的深度

二、二叉树的层次遍历

1.层次遍历

2.算法思想:

3.算法演示:

4.代码实现:

三、由遍历序列构造二叉树

1.遍历序列构造二叉树

2.前序+中序

3.后序+中序

4.层序+中序


一、二叉树的先中后序遍历

1.先中后序遍历

(1)二叉树的递归特性:

        ①要么是个空二叉树;

        ②要么是由“根结点+左子树+右子树”组成的二叉树。

(2)基于此,给出三种遍历方式:

        ①先序遍历(先根遍历):左右(NLR)

        ②中序遍历(中根遍历):(LNR)

        ③后序遍历(后根遍历):左右(LRN)

(3)先序遍历、中序遍历、后序遍历

        ①先序遍历:

        先访问根结点,再访问该根结点的左子树结点,最后访问该根结点的右子树结点;如果其左子树或右子树为分支结点,则需要对分支结点再进行一遍先序遍历,这种访问方式也是一种递归方式。

        ②中序遍历:

        先访问根结点的左子树结点,再访问根结点,最后访问根结点的右子树结点;如果其左子树或右子树为分支结点,则需要对分支结点再进行一遍中序遍历。

        ③后序遍历:

        先访问根结点的左子树结点,再访问根结点的右子树结点,最后访问根结点;如果其左子树或右子树为分支结点,则需要对分支结点再进行一遍后序遍历。


2.举例


 3.先中后序遍历和前中后缀的关系

  (1)先来看一个例子:

 

 (2)求其先中后序遍历遍历序列分别为:

        ①先序遍历:- + a * b - c d / e f

        ②中序遍历:a+b*c-d-e/f

        ③后序遍历:abcd-*+ef/-

 (3)求其前中后缀表达式:

        ①前缀表达式:- + a * b - c d / e f

        ②中缀表达式:a+b*\left ( c-d \right )-e/f

        ③后缀表达式:abcd-*+ef/-

 (4)观察(2)(3)可得在算术表达式“分析树”中所得到的先中后序遍历即为该算术表达式的前中后缀表达式,只不过其中中缀表达式要自己加界限符。


4.代码实现

(1)先序遍历代码:

若二叉树为空,则什么也不做;

若二叉树非空:①访问根结点;

                         ②先序遍历左子树;

                         ③先序遍历右子树。

typedef struct BiTNode {
	int data;
	struct BiTNode* lchild, * rchild;
}BiTNode,*BiTree;

void PreOrder(BiTree T)
{
	if (T != NULL)
	{
		visit(T);                访问根结点,visit()执行相关访问操作的函数,比如打印...
		PreOrder(T->lchild);     //递归遍历左子树
		PreOrder(T->rchild);     //递归遍历右子树
	}
}

(2)中序遍历代码:

若二叉树为空,则什么也不做;

若二叉树非空:①中序遍历左子树;

                         ②访问根结点;

                         ③中序遍历右子树。

void InOrder(BiTree T)
{
	if (T != NULL)
	{
		InOrder(T->lchild);		//递归遍历左子树
		visit(T);				//访问根结点
		InOrder(T->rchild);		//递归遍历右子树
	}
}

(3)后序遍历代码:

若二叉树为空,则什么也不做;

若二叉树非空:①后序遍历左子树;

                         ②后序遍历右子树;

                         ③访问根结点。

void PostOrder(BiTree T)
{
	if (T != NULL)
	{
		PostOrder(T->lchild);	//递归遍历左子树
		PostOrder(T->rchild);	//递归遍历右子树
		visit(T);				//访问根结点
	}
}

5.求遍历序列

(1)求先序遍历序列

 (2)求中序遍历序列

(3)求后序遍历序列 


6.应用:求树的深度

后序遍历算法变种之求树的深度:

int treeDepth(BiTree T)
{
	if (T == NULL)
		return 0;
	else
	{
		int l = treeDepth(T->lchild);
		int r = treeDepth(T->rchild);
		return l > r ? l + 1 : r + 1;		//树的深度=Max(左子树深度,右子树深度)+1
	}
}


二、二叉树的层次遍历

1.层次遍历

如图所示,层次遍历即一层一层访问数的结点:A B C D E F G H I J K L;


2.算法思想:

(1)初始化一个辅助队列;

(2)根结点入队;

(3)若队列非空,则队头结点出队,并访问该结点,然后将其左、右子树结点插入队尾(如果有的话)。


3.算法演示:


4.代码实现:

//二叉树的结点(链式存储)
typedef struct BiTNode {
	char data;
	struct BiTNode* lchild, * rchild;
}BiTNode,*BiTree;

//链式队列结点
typedef struct LinkNode {
	BiTNode* data;                  //存指针而不是结点,节省内存空间
	struct LinkNode* next;
}LinkNode;

typedef struct {
	LinkNode* front, * rear;		//队头队尾指针
}LinkQueue;

//层序遍历
void LevelOrder(BiTree T)
{
	LinkQueue Q;
	InitQueue(Q);						//初始化辅助队列
	BiTree p;
	EnQueue(Q, T);						//将根结点入队
	while (!IsEmpty(Q))					//队列不空则循环
	{
		DeQueue(Q, p);					//对头结点出队
		visit(p);						//访问出队结点
		if (p->lchild != NULL)
			EnQueue(Q, p->lchild);		//左孩子入队
		if (p->rchild != NULL)
			EnQueue(Q, p->rchild);		//右孩子入队
	}
}


三、由遍历序列构造二叉树

1.遍历序列构造二叉树

(1)若只给出一棵二叉树的前/中/后/层序遍历中的一种,不能确定唯一一棵二叉树。

(2)由遍历序列构造二叉树需要:

            ①前序+中序遍历序列;

        或②后序+中序遍历序列;

        或③层序+中序遍历序列;


2.前序+中序

(1)方法:

①由前序遍历序列判断出根结点;

②由根结点在中序遍历序列中的位置判断出左子树和右子树的前序和中序遍历序列;

③分别对左右子树的前序和中序遍历序列再进行①②的分析判断出所有的结点;

(2)举例:

 ①由前序遍历序列第一个D判断出D为根结点,其所在中序遍历序列的位置判断出:

        左子树中序序列:EAF;前序序列:AEF;

        右子树中序序列:HCBGI;前序序列:BCHGI;

如下图:

 ②由左子树前序序列判断左子树根结点为A,由其所在左子树中序序列的位置判断出:

        根结点A的左子树为E;右子树为F;

③由右子树前序序列判断右子树根结点为B,由其所在右子树中序序列的位置判断出:

        根结点B的左子树中序序列为HC;前序序列为CH;

        根结点B的右子树中序序列为GI;前序序列为GI;

如下图:

 ④由所示橘色结点的前序序列CH判断这里的根结点为C;由C所在中序序列的位置判断出H为C的左子树结点;

⑤由所示绿色结点的前序序列GI判断这里的根结点为G;由G所在中序序列的位置判断出I为G的右子树结点;

如下图:


3.后序+中序

(1)方法

①由后序遍历序列判断出根结点;

②由根结点在中序遍历序列中的位置判断出左子树和右子树的后序和中序遍历序列;

③分别对左右子树的后序和中序遍历序列再进行①②的分析判断出所有的结点;

(2)举例:

①由后序遍历序列判断出根结点为D;由D在中序序列的位置判断出:

        D的左子树中序序列:EAF;后序序列:EFA;

        D的右子树中序序列:HCBGI;后序序列:HCIGB;

如下图:

 ②由图中橘色部分后序序列EFA判断出这里的根结点为A;由A在中序序列EAF所在位置判断出A的左子树结点为E,右子树结点为F;

③由图中绿色部分后序序列HCIGB判断出这里的根结点为B;由B在中序序列HCBGI所在位置判断出:

        B的左子树结点的中序序列:HC;后序序列:HC;

        B的右子树结点的中序序列:GI;后序序列:IG;

如下图:

 ④由橘色部分后序序列HC判断这里的根结点为C,由C在中序序列的位置判断H为C的左子树结点;

⑤由绿色部分后序序列IG判断这里的根结点为G,由G在中序序列的位置判断I为G的右子树结点;

如下图:


4.层序+中序

(1)方法:

①由层序遍历序列判断根结点;

②由根结点在中序序列中的位置判断根结点的左右子树的中序序列(注意可能会有空树的情况);

③由层序遍历序列判断下一层的根结点;

④由下一层根结点在中序序列中的位置判断下一层根结点的左右子树的中序序列(注意空树);

⑤反复以上分析,判断出所有的结点;

(2)举例:

 ①由层序遍历序列判断D为根结点;由D所在中序序列中的位置判断:

        D的左子树中序序列:EAF;右子树中序序列:HCBGI;

如下图:

 ②由层序遍历序列判断第二层的根结点分别为A和B;由A和B在中序序列中的位置判断:

        A的左子树结点为E,右子树结点为F;

        B的左子树中序序列为HC,右子树中序序列为GI;

如下图:

③上图所示,第三层分别为:E、F、HC中出一个、GI中出一个;

④由层序序列判断HC中出C,GI中出G;

⑤最后由中序序列判断H为C的左子树结点;I为G的右子树结点,如下图:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构——二叉树的先中后序遍历 的相关文章

随机推荐

  • python中的模块与包详解

    目录 一 什么是模块 二 模块的导入 1 import 模块名 2 from 模块名 import 功能名 3 from 模块名 import 4 as定义别名 模块导入总结 三 自定义模块 制作自定义模块 用pycharm演示 测试模块
  • 【C语言】冒泡排序算法和冒泡排序的时间复杂度

    提示 xff1a 冒泡排序算法是非常重要的算法 xff0c 一定要熟练掌握 思路可以参考一位大佬博主的博客 xff1a 帅地 介绍的十分详细 xff0c 理解了之后 xff0c 可以参考我的代码 xff0c 是入门级别的 xff0c 比较好
  • Vbox遇到“Destination host unreachable“问题的解决之法

    在上一篇 虚拟机的网络配置与连接 中 xff0c 有讲述到Vmware遇到Destination host unreachable 问题的解决之法 xff0c 而这一篇文章我将说到Vbox的遇到 34 Destination host un
  • 以太网链路聚合与VRRP

    文章目录 一 以太网链路聚合1 1 链路聚合的含义以及作用1 2 链路聚合的配置 二 VRRP2 1 VRRP概述2 2VRRP术语2 3 VRRP工作原理2 4 VRRP的基本配置2 5VRRP总结 三 总结 一 以太网链路聚合 1 1
  • Ubuntu 20.04 系统迁移

    一 前言 现实工作中需要在Intel NUC上装一个Ubuntu 20 04系统 xff0c 并运行ROS以及相关的很多功能包 xff0c 但如果直接安装新新系统 xff0c 之前的大量环境变量要重新去配置 xff0c 所以考虑说将原先的U
  • 电大计算机考试答案

    中央电大计算机基础考试题库大全 基础知识 单选题 1 自计算机问世至今已经经历了四个时代 xff0c 划分时代的主要依据是计算机的 A 规模 B 性能 C 功能 D 构成元件答案 D 2 当前的计算机一般被认为是第四代计算机 xff0c 它
  • 用opencv识别颜色并输出坐标

    1首先安装opencv pip install opencv python 参考https blog csdn net qq 42114833 article details 128648458 spm 61 1001 2014 3001
  • ROS开发(ubuntu)笔记·1

    学习网址 xff1a Introduction GitBook autolabor com cn b站 xff1a 奥特学园 ROS机器人入门课程 ROS理论与实践 零基础教程 哔哩哔哩 bilibili 创建一个ROS Workspace
  • ROS通信机制~话题通信(Publisher&Subscriber)·笔记2

    系列文章目录 xff1a ROS开发 xff08 ubuntu xff09 笔记 1 嘻 嘻的博客 CSDN博客 ROS通信机制 服务通信 server amp client 笔记3 嘻 嘻的博客 CSDN博客 话题通信 理论模型 xff1
  • SDL2.0在linux/ubuntu系统中更新使用指导

    前言 个人喜好原因 xff0c 写OpenGL的程序都喜欢用SDL做框架 xff0c 没有Qt那么臃肿 xff0c 也没有glut那么坑跌 在不失灵活性的情况下保持了自己的轻量 SDL2 0在今年很早的时候时候就发布了 xff0c 几天就来
  • Tensorflow-gpu安装教程(window11和window10一样)

    1 安装最新版Pycharm xff08 最常见的编译器 xff09 下载官网 xff1a https www jetbrains com pycharm 可以安装到D盘 xff0c 版本免费社区版就行 xff0c 推荐装最新版 2 安装最
  • T265 安装(Realsense SDK和Realsense-ros)

    一 写在前面 硬件配置 xff1a Jeston xavier NX 机载电脑 xff0c 板载6002E 设备如图 xff1a T265双目摄像头 二 Realsense SDK和Realsense ros的介绍 在我看来 xff0c R
  • SysTick 定时器的使用

    手册说明 代码模块 SysTick h ifndef SysTick H define SysTick H include 34 system h 34 void SysTick Init u8 SYSCLK void delay us u
  • FreeRTOS互斥量的实验

    互斥量又称互斥信号量 xff08 本质是信号量 xff09 xff0c 是一种特殊的二值信号量 xff0c 它和 信号量不同的是 xff0c 它支持互斥量所有权 递归访问以及防止优先级翻转的特性 xff0c 用于实现对临界资源的独占式处理
  • FreeRTOS cpu利用率简单介绍

    1 CPU 利用率简介 CPU 使用率其实就是系统运行的程序占用的 CPU 资源 xff0c 表示机器在某段时 间程序运行的情况 xff0c 如果这段时间中 xff0c 程序一直在占用 CPU 的使用权 xff0c 那么可 以认为 CPU
  • 直播的推流与拉流如何在uniapp中实现?

    直播的推流和拉流是实现直播功能的两个关键步骤 xff0c 下面是它们的实现方式 xff1a 推流 xff1a 1 采集视频和音频数据 xff1a 使用摄像头和麦克风等设备 xff0c 采集视频和音频数据 2 编码数据 xff1a 将采集到的
  • Windows下GCC安装和使用

    GCC是由GNU开发的编程语言译器 最近复现代码时需要编译源文件 xff0c 总是报错 xff0c 后来查验报错原因后 xff0c 是由于电脑没能安装GCC C 语言编译器用于把源代码编译成最终的可执行程序 但是本人不是很懂编译原理 xff
  • AUTOSAR——AUTOSAR基础

    一 AUTOSAR AUTOSAR全称为 AUTomotive Open System ARchitecture xff0c 译为 汽车开放系统体系结构 二 AUTOSAR核心思想 1 xff09 提倡 在标准上合作 xff0c 在实现上竞
  • 麦克纳姆轮(麦轮)原理

    一 麦轮原理 麦克纳姆轮 xff1a 简称麦轮 xff0c 由轮毂和围绕轮毂的辊子组成 辊子 xff1a 没有动力的从动小滚轮 麦克纳姆轮辊子轴线和轮毂轴线夹角是45度 A轮 xff08 左旋 xff09 与B轮 xff08 右旋 xff0
  • 数据结构——二叉树的先中后序遍历

    本节内容为Bilibili王道考研 数据结构 P43 P45视频内容笔记 目录 一 二叉树的先中后序遍历 1 先中后序遍历 2 举例 3 先中后序遍历和前中后缀的关系 4 代码实现 5 求遍历序列 6 应用 xff1a 求树的深度 二 二叉