【数据结构】二叉树的遍历

news/2024/5/15 20:58:01/文章来源:https://blog.csdn.net/weixin_45481821/article/details/126794643

文章目录

5.3 二叉树的遍历

5.3.1 概述

5.3.2 遍历方式【重点】

5.3.3 遍历方式:递归实现【重点】

5.3.4 遍历方式:非递归实现

5.3 二叉树的遍历

5.3.1 概述

  • 二叉树的遍历:沿着某条搜索路径对二叉树中的结点进行访问,使得每个结点均被访问一次,而且仅被访问一次。“访问”的含义较为广泛,例如:输出结点信息。

  • 二叉树有3条搜索路径:

    1. 先上后下

    2. 先左后右

    3. 先右后左

  • 对应3条搜索路径,二叉树有7种遍历方式:

    • 先上后下

      1. 层次遍历

    • 先左后右 (D data根、 L left左、R right 右)

      1. DLR (先根遍历、先序遍历、先根序遍历)

      2. LDR (中根遍历、中序遍历、中根序遍历)

      3. LRD (后根遍历、后序遍历、后根序遍历)

    • 先右后左

      1. DRL

      2. RDL

      3. RLD

  • 需要遍历的二叉树

     

    A

    B

    C

    D

    E

    F

    G

    H

    K

5.3.2 遍历方式【重点】

1) 层次遍历

  • 若二叉树为空,则为空操作;否则,按自上而下先访问第0层的根节点,然后再从左到右依次访问各层次中的每一个结点。

  • 层次遍历序列

    ABECFDGHK

2)先根(序)遍历 DLR

  • 若二叉树为空,则为空操作,否则

    1. 访问根节点

    2. 先根遍历左子树

    3. 先根遍历右子树

    4.  

  • 先根遍历序列

    ABCDEFGHK

3)中根(序)遍历 LDR

  • 若二叉树为空,则为空操作;否则

    1. 中根遍历左子树

    2. 访问根节点

    3. 中根遍历右子树

  • 中根遍历序列

    BDCAEHGKF

 

4)后根(序)遍历LRD

  • 若二叉树为空,则为空操作;否则

    1. 后根遍历左子树

    2. 后根遍历右子树

    3. 访问根节点

  • 后根遍历序列

    DCBHKGFEA

 

5)练习

  • 练习1:

 

先根序遍历:ABDEGCFH

中根序遍历:DBGEAFHC

后根序遍历:DGEBHFCA

  • 练习2:

     

    先根序遍历:ABDEGJHCFIKL

    中根序遍历:DBJGEHACKILF

    后根序遍历:DJGHEBKLIFCA

  • 练习3:

     

    先根序遍历:ABCDEFGHK

    中根序遍历:BDCAEHGKF

    后根序遍历:DCBHKGFEA

5.3.3 遍历方式:递归实现【重点】

1)算法:先根(序)遍历 DLR

public void preRootTraverse(BiTreeNode T) {if(T != null) {System.out.print(T.data);       //输出根元素preRootTraverse(T.lchild);      //先根遍历左子树preRootTraverse(T.rchild);      //先根遍历右子树}
}

2)算法:中根(序)遍历 LDR

public void inRootTraverse(BiTreeNode T) {if(T != null) {inRootTraverse(T.lchild);       //中根遍历处理左子树System.out.print(T.data);       //访问根节点inRootTraverse(T.rchild);       //中根遍历处理右子树}
}

3)算法:后根(序)遍历LRD

public void postRootTraverse(BiTreeNode T) {if(T != null) {postRootTraverse(T.lchild);     //后根遍历左子树postRootTraverse(T.rchild);     //后根遍历右子树System.out.print(T.data);       //访问根结点}
}

4)动画演示:后根遍历

 

5.3.4 遍历方式:非递归实现

1)分析:先根(序)遍历 DLR

  • 借助一个==栈==来记录当前被访问结点的右孩子结点,以便遍历完一个结点的左子树后,可以继续遍历该结点的右子树。

  • 实现思想:

    1. 将根节点压栈

    2. 从栈顶获得需要遍历的结点A,并访问结点A。

    3. 此时结点A有左孩子直接访问,结点A有右孩子压入栈顶

    4. 同时沿着左子树继续搜索,重复步骤3

    5. 当左子树访问完成后,重复步骤2依次访问对应的右子树

2)算法:先根(序)遍历 DLR【重点】

public void preRootTraverse() {BiTreeNode T = root;if( T != null ) {LinkStack S = new LinkStack();      // 创建栈记录没有访问过的右子树S.push(T);                          // 将根节点压入栈顶while(!S.isEmpty()) {               // 栈中只要有数据,表示继续遍历T = S.pop();                    // 弹出栈顶数据System.out.print(T.data);       // 结点被访问while(T != null) {              // T指针,访问每一个左孩子if(T.lchild != null) {      // 输出左孩子System.out.print(T.lchild.data);}if(T.rchild != null) {      // 将右孩子压栈T.push(T.rchild);}T = T.lchild;               // 访问下一个左孩子}}}
}

3)分析:中根(序)遍历 LDR

  • 借助一个==栈==来记录遍历过程中所经历的而未被访问的所有结点,以便遍历完左子树后能顺利的返回到它的父节点。

  • 实现思想

    1. 从非空二叉树的根节点出发

    2. 沿着该结点的左子树向下搜索,在搜索过程中将遇到的每一个结点依次压栈,直到二叉树中最左下结点压栈为止,

    3. 然后从栈中弹出栈顶结点并对其进行访问,访问完成后再进入该结点的右子树,

    4. 并用上述相同的方法去遍历该结点的右子树,直到二叉树中所有的结点都被访问。

4)算法:中根(序)遍历 LDR

public void inRootTraverse() {BiTreeNode T = root;if(T != null) {LinkStack S = new LinkStack();S.push(T);                          //将根节点压入到栈顶while( !S.isEmpty() ) {             //栈中有数据,表示遍历未完成//1 将所有的左孩子压栈while(S.peek() != null) {       //栈顶的元素不为空,注意:不是弹栈// 获得栈顶,BiTreeNode temp = (BiTreeNode)S.peek();// 并将左孩子压入栈顶S.push(temp.lchild);}S.pop();                        //将栈顶的空元素弹出//2 依次弹出栈,访问当前节点,如果有右孩子继续压栈if(! S.isEmpty()) {T = (BiTreeNode)S.pop();System.out.print(T.data);       //访问栈顶S.push(T.rchild);}}}
}

5)分析:后根(序)遍历LRD

  • 借助一个栈用记载遍历过程中所经历而未被访问的所有结点。

    • 确定顶点结点是否能访问,需要知道该结点的右子树是否被遍历完成。

    • 引入两个变量,一个访问标记变量flag和一个结点指针p

      • flag永不标记当前栈顶结点是否被访问

      • p指向当前遍历过程中最后一个被访问的结点。

  • 实现思想

    1. 从非空二叉树的根节点出发

    2. 将所有的左孩子相继压栈,

    3. 然后获得栈中每个结点A,如果该结点A没有右孩子或右孩子已经访问过,将访问结点A

    4. 如果结点A有右孩子或右孩子未被访问过,继续压栈

    5. 通过标记,使程序开始出了新添加进入的结点。

6)算法:后根(序)遍历LRD

public void postRootTraverse() {BiTreeNode T = root;if( T != null) {LinkStack S = new LinkStack();S.push(T);// 声明两个变量Boolean flag;               //用于记录是否被访问BiTreeNode p;               //用于记录上一次处理的结点while(! S.isEmpty() ) {//1 将所有的左孩子压栈while(S.peek() != null) {       //栈顶的元素不为空,注意:不是弹栈// 获得栈顶,BiTreeNode temp = (BiTreeNode)S.peek();// 并将左孩子压入栈顶S.push(temp.lchild);}S.pop();                        //将栈顶的空元素弹出while( !S.isEmpty() ) {T = (BiTreeNode) S.peek();if(T.rchild == null || T.rchild == p) {  // 没有右孩子 或 已经访问过System.out.print(T.data);S.pop();                    //弹出p = T;                      //记录刚才访问过的flag = true;            //没有新元素,继续访问} else {S.push(T.rchlid);flag = false;           //新右子树添加}if(!flag) {break;              //如果有右子树,需要重新开始}}}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_6529.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

grpc|protobuf的安装、编译、运行笔记(C++)

一、下载grpc源码 如果你的电脑/服务器可以做代理,然后稳定链接上 GitHub 那么完全可以按照 GitHub 的官方文档来操作,我这里采用 Gitee 镜像来操作 git clone https://gitee.com/jiangxy__loey/grpc.git二、下载依赖库 进入grpc目录,然后…

为什么残差连接的网络结构更容易学习?

为什么残差连接的网络结构更容易学习? 【写在前面】 不仅仅在resnet中,在各种网络结构中大家都喜欢使用残差连接的设计,并声称这有利于网络的优化,这是为什么呢?能给出一个有说服力的答案吗? Why the re…

1.数据校验-拦截器-全局异常-json数据处理

目录 1.数据校验-拦截器-全局异常-json数据处理 1. JSR303 2. JSR303中含有的注解 3. spring中使用JSR303进行服务端校验 3.1 导入依赖包 3.2 添加验证规则 3.3执行校验 3.4 错误信息的展示 4. SpringMVC定义Restfull接口 5.1 增加spring配置 5.2 Controller 5.3 格…

Mstsc(远程桌面连接)命令的高级用法

Mstsc远程桌面连接,这个是微软操作系统自带的一个命令,相信很多人都用过,但是如果说这个命令还有高级用法,估计很多人都没有用过,其实这个命令还是很强大的,今天咱们就来说一下mstsc的高级用法Mstsc远程桌面连接,这个是微软操作系统自带的一个命令,相信很多人都用过,但…

20220912--CSP-S模拟4

A. 石子游戏 B. 大鱼吃小鱼 C. 黑客 D. 黑客-续A. 石子游戏 首先了解一个叫做 \(\operatorname{Nim}\) 游戏的玩意 通常的 \(\operatorname{Nim}\) 游戏的定义是这样的: 有若干堆石子,每堆石子的数量都是有限的,合法的移动是“选择一堆石子并拿走若干颗(不能不拿)” 如果轮…

自制操作系统日志——第十二天

自制操作系统日志——第十二天 从今天开始,我们将花费两天的时间来进行计算机中定时器的制作。有了定时器后,才能够为程序和cpu更加便利的进行计时。可能会稍难一些了!!! 做好准备,冲!&#xf…

ConcurrentLinkedQueue解析

概述 ConcurrentLinkedQueue实际对应的是LinkedList,是一个线程安全的无界队列,但LinkedList是一个双向链表,而ConcurrentLinkedQueue是单向链表。ConcurrentLinkedQueue线程安全在于设置head、tail以及next指针时都用的cas操作,而且node里的…

00Android studio安装

目录一.下载Android studio二.安装Android studio三.打开软件一.下载Android studio 官网:https://developer.android.google.cn/studio 下载:由于是国外的网站,国内下载会比较慢 二.安装Android studio 打开: 点击【Next】 点击…

猿创征文|瑞吉外卖——管理端_员工管理

个人名片: 博主:酒徒ᝰ. 专栏:瑞吉外卖 个人简介:沉醉在酒中,借着一股酒劲,去拼搏一个未来。 本篇励志:一本好书,就像高级武功秘籍一样,哪怕只是从里面领悟到个一招半势&…

C# StringBuilder 底层深入原理分析以及使用详解

目录前言什么是StringBuilderStringBuilder的成员StringBuilder增加元素原理StringBuilder扩容原理Capacity:1,元素数量:0Capacity:1,元素数量:1Capacity:2,元素数量:2Ca…

开学季征文|卷生卷死之新学期大学生自救指南!!!

你好,这里是前情提要 正所谓 “ 宁可卷死自己,也要卷死同学 ” ,在这个万物皆卷的时代,“卷”似乎早已与我们变得不可分割血脉相融,有道是卷卷更健康。我也知道卷卷更好,可是天不遂人愿,因为疫情…

Redis_09_Redis集群实现Sentinel哨兵应对高可用

文章目录一、前言二、Sentinel原理2.1 Sentinel原理2.2 Sentinel选主2.3 Sentinel功能小结三、Sentinel实践3.1 Sentinel配置3.2 实践:Sentinel基本使用3.2.1 实践:Sentinel搭建3.2.2 实践:主节点宕机之后的选主过程(Sentinel保证高可用)3.2.…

ERROR 2003 (HY000) Can‘t connect to MySQL server on ‘localhost3306‘ (10061)解决办法

这个解决办法是我根据网上一系列的方法准备突然成功的,所以我想可能是由于本身其不稳定造成的 首先,我在官网上下载了mysql文件,这个网上随便找都能找到怎么下载的 然后打开文件后,发现没有my.ini 所以我就找了一个文档放了进去…

【线性代数】MIT Linear Algebra Lecture 6: Column space and nullspace

Author| Rickyの水果摊 Time | 2022.9.12 Lecture 6: Column space and nullspace Lecture Info Instructor: Prof. Gilbert Strang Course Number: 18.06 Topics: Linear Algebra Official Lecture Resource: Resource Index of Linear Algebra …

HCIP-双机热备

一,双机热备原理 1.1双机热备简介FW部署在网络出口位置时,如果发生故障会影响到整网业务。为提升网络的可靠性,需要部署两台FW并组成双机热备。双机热备需要两台硬件和软件配置均相同的FW。两台FW之间通过一条独立的链路连接,这条链路通常被称之为“心跳线”。两台FW通过心…

美团面试官:高并发、任务执行时间短的业务怎样使用线程池?

前言 无论是互联网大厂还是一些中游公司的面试基本都会问到多线程与并发编程的知识,所以今天小编在这里做了关于这方面知识的一个笔记分享送给即将面试跳槽的程序员朋友们! 首先关于多线程与并发的知识总结了一个思维导图,分享给大家 如果你…

【Pytorch】2022 Pytorch基础入门教程(完整详细版)

一、Pytorch 1.1 简介 Pytorch是torch的python版本,是由Facebook开源的神经网络框架,专门针对 GPU 加速的深度神经网络(DNN)编程。Torch 是一个经典的对多维矩阵数据进行操作的张量(tensor )库&#xff0…

从校园智能门锁预见万物互联的未来

随着物联网、移动互联网、大数据、云计算等信息技术的创新发展,被信息化驱动的教育行业实现了技术深化融合,智慧校园正逐步落地生根、开花结果。校园智能门锁是智慧校园的基础载体,也是实现教育信息化的基础载体。 NO.1校园智能门锁构建一体化…

【CSDN竞赛第五期】“三而竭”采用等比求和公式法的思考

原题题目 一鼓作气再而衰三而竭。 小艺总是喜欢把任务分开做。小艺接到一个任务,任务的总任务量是n。 第一天小艺能完成x份任务,第二天能完成x/k ... ...第t天能完成x/(k^(t-1))。 小艺想知道自己第一天至少完成多少才能完成最后的任务。 公式推导 第一…

[项目管理-25]:高效沟通的利器,结构思考力与树形结构化表达

作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客 本文网址: 目录 前言: 第1章 结构化思考力概述 1.1 非结构化思考力的问题与结构化思路力的好处 1.2 什么是结构化思路力 1.3…