数据结构——遍历二叉树

目录

什么是遍历二叉树

 根据遍历序列确定二叉树

例题(根据先序中序以及后序中序求二叉树)

 遍历的算法实现

先序遍历

中序遍历 

后序遍历

遍历算法的分析

二叉树的层次遍历

二叉树遍历算法的应用

二叉树的建立

复制二叉树

 计算二叉树深度

 计算二叉树结点总数


什么是遍历二叉树

遍历定义-- 顺着某一条搜索路径巡访二叉树中的结点,使得每个结点均被访问一次,而且仅被访问一次(又称周游)。

  • “访问”的含义很广,可以是对结点作各种处理,如:输出结点的信息、修改结点的数据值等,但要求这种访问不破坏原来的数据结构。

遍历目的-- 得到树中所有结点的一个线性排列。

遍历用途--它是树结构插入、删除、修改、查找和排序运算的前提,是二又树一切运算的基础和核心。

遍历方法

依次遍历二叉树的三个组成部分,便是遍历了整个二叉树。

若规定先左后右,则只有三种情况:

由二叉树的递归定义可知,遍历左子树和遍历右子树可如同遍历二叉树一样“递归”进行。

先序(DLR)遍历二叉树的操作定义:

(1)访问根结点;

(2)先序遍历左子树;

(3)先序遍历右子树。

注:根的左子树遍历完(左子树的左子树、左子树的右子树...)才轮到根的右子树进行遍历。

 示例如下:

 中序遍历二叉树的操作定义:

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

(1)中序遍历左子树;

(2)访问根结点;

(3)中序遍历右子树。

示例:

 后序遍历二叉树的操作定义:

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

(1)后序遍历左子树;

(2)后序遍历右子树;

(3)访问根结点。

 示例:

例题:

解析

先序: 先根结点A,再遍历根A的左子树,左子树遍历完,才轮到遍历右子树,左子树的根B,再根B的左子树,以D为根,再根D的左子树,没有就根D的右子树G,根G的左子树和右子树都没有,根D的树遍历完,再根B的右子树,没有,就可以遍历根A的右子树了,根C的左子树先遍历,以根E的树,根E的左子树没有,遍历根E的右子树,以H为根的左子树和右子树都没有,遍历根C的右子树,以F为根的左右子树都没有,先序遍历结束。

中序:先以A为根的左子树,再B为根的左子树,再以D为根的左子树,没有就输出根D,再根D的右子树G输出,以B为根的左子树结束就输出根B,再遍历B的右子树,没有就输出根A,再遍历根A的右子树,以C为根的左子树,再以E为根的左子树,没有就输出根E,根E的右子树H,根H的左子树没有,输出根H,根H的右子树没有,根C的左子树遍历完毕,输出根C,再遍历根C的右子树,以F为根的左子树没有,输出根F,根F的右子树没有。

后序:以A为根的左子树先遍历,以B为根的左子树先遍历,以D为根的左子树先遍历,没有就遍历根D的右子树,根G的左子树不存在,右子树也不存在,后序输出根结点G,根D的左右子树都遍历完了,输出根结点D,B的左子树遍历完,遍历其右子树,右子树不存在,输出根结点B,根A的左子树遍历完,遍历其右子树,根C的左子树先遍历,根E的左子树先遍历,不存在,遍历根E的右子树,根H的左右子树都不存在,输出根结点H,E的左右子树都遍历完,输出根结点E,C的左子树遍历完,遍历其右子树,根F的左右子树都不存在,输出根结点F,根C的左右结点都遍历完,输出根结点C,根A的左右子树都遍历完,输出根结点A。

请写出下图所示二叉树的先序、中序和后序遍历顺序。

 根据遍历序列确定二叉树

  • 若二叉树中各结点的值均不相同,则二叉树结点的先序序列、中序序列和后序序列都是唯一的。
  • 由二叉树的先序序列和中序序列,或由二叉树的后序序列和中序序列可以确定唯一一棵二叉树

例题(根据先序中序以及后序中序求二叉树)

已知先序和中序序列求二叉树

例:已知二叉树的先序和中序序列,构造出相应的二叉树

先序:A  B  C  D  E  F  G  H  I  J

中序:C  D  B  F  E  A  I  H  G  J

首先从先序中可以知道这棵大树的根为A,已知根A后,从中序序列中可以得知C  D  B  F  E是这棵大树的左子树,I  H  G  J是这棵大树的右子树;再从先序序列中B  C  D  E  F得知B是左子树的根,G  H  I  J是右子树的根,再从中序序列中可以知道C  D是根为B的树的左子树,F  E是右子树,以此类推,可以构造相对应的二叉树。

已知后序和中序序列求二叉树

 例:已知一棵二叉树的

中序序列:B  D  C  E  A  F  H  G

后序序列:D  E  C  B  H  G  F  A,请画出这棵二叉树。

类似的,我们可以先从后序序列中知道这棵大树的根结点为A,再从中序序列中得知B  D  C  E是以A为根结点的左子树,F  H  G是其右子树,再从后序序列D  E  C  B中知道B是左子树的根结点,F是左子树H  G  F的根结点,再从中序序列可以得出以B为根结点的树没有左子树,其右子树为D  C E,以F为根结点的左子树不存在,其右子树为H  G,以此类推可以画出完整的二叉树。

 遍历的算法实现

先序遍历

 步骤:

 先序的遍历序列为ABCD

算法实现

Status PreOrderTraverse(BiTree T)
{if (T == NULL)return OK;//空二叉树else{visit(T);//访问根结点PreOrderTraverse(T->lchild);//递归遍历左子树PreOrderTraverse(T->rchild);//递归遍历右子树}
}

过程:指针T指向我们的二叉树的根结点,把根结点的指针T传递给前序遍历,判断T是否为空,此时不为空,输出A结点的数据域上的值,然后对左子树进行先序遍历,将当前结点的左孩子的地址传递给它自身,调用自身函数后,输出当前指针的数据域的值,也就是B结点的值,接下来访问B结点的左子树,为空返回,然后再访问B的右子树,此时T指向D结点,不为空输出其值,D结点的左右子树都为空,返回,依次返回到以A结点的树,其左子树遍历完毕,继续遍历其右子树。

中序遍历 

 

 步骤:

 中序遍历序列:BDAC

算法实现

Status InOrderTraverse(BiTree T)
{if (T == NULL)return OK;else{InOrderTraverse(T->lchild);//递归遍历左子树visit(T);//访问根结点InOrderTraverse(T->rchild);//递归遍历右子树}
}
后序遍历

 

步骤:

后序遍历序列:DBCA

算法实现

Status PostOrderTraverse(BiTree T)
{if (T == NULL)return OK;else{PostOrderTraverse(T->lchild);//递归遍历左子树PostOrderTraverse(T->rchild);//递归遍历右子树visit(T);//访问根结点}
}

遍历算法的分析

 如果去掉输出语句,从递归的角度看,三种算法是完全相同的,或说这三种算法的访问路径是相同的,只是访问结点的时机不同。

从虚线的出发点到终点的路径上,每个结点经过3次。

第1次经过时访问=先序遍历

第2次经过时访问=中序遍历

第3次经过时访问=后序遍历

 

二叉树的层次遍历

第一个访问根结点a,然后从左到右访问第二层,a的孩子b和f,再访问孩子的孩子。

 对于一棵二叉树,从根结点开始,按从上到下、从左到右的顺序访问每一个结点。

每一个结点仅仅访问一次。

 算法设计思路使用一个队列

 1、将根结点进队;
 2、队不空时循环:从队列中出列一个结点*p,访问它;

  • 若它有左孩子结点,将左孩子结点进队;
  • 若它有右孩子结点,将右孩子结点进队。

 

遍历描述:首先,根结点a入队, 队列开始出队,第一个结点是

a,a出队,然后把a的左右孩子b、f入队,再从队列中拿出最前一个结点b出队,把它的左右孩子c、d入队,再拿出f出队,把它的左孩子g入队,现在队列中还有cdg,把c出队,它的左右孩子入队,没有就拿下一个结点出队,以此类推。

代码实现:

 使用队列类型定义如下

typedef struct
{BTNode data[MaxSize];//存放队中元素int front, rear;//队头和队尾指针
}SqQueue; //顺序循环队列类型

二叉树层次遍历算法:

void LevelOrder(BTNode* b)
{BTNode* p;SqQueue* qu;InitQueue(qu);//初始化队列enQueue(qu,b);//根结点指针进入队列while (!QueueEmpty(qu)){deQueue(qu,p);//出队结点printf("%c",p->data);//访问结点pif (p->lchild != NULL)enQueue(qu,p->lchild);//有左孩子时将其出队if (p->rchild != NULL)enQueue(qu, p->rchild);//有右孩子时将其出队}
}

二叉树遍历算法的应用

二叉树的建立
  • 按先序遍历序列建立二叉树的二叉链表

例:已知先序序列为:ABCDEGF

(1)从键盘输入二叉树的结点信息,建立二叉树的存储结构;

(2)在建立二叉树的过程中按照二叉树先序方式建立;

用#表示空字符

代码实现

Status CreateBiTree(BiTree& T)//链式存储
{scanf(&ch);//cin>>ch;if (ch == "#")T = NULL;else{if (!(T=(BiTNode*)malloc(sizeof(BiTree))))//从内存当中分配一个结点空间exit(OVERFLOW);//T=new NiTNode;T->data = ch;CreateBiTree(T->lchild);//构造左孩子CreateBiTree(T->rchild);//构造右孩子}return OK;
}//CreateBiTree
复制二叉树

如果是空树,递归结束;

否则,申请新结点空间,复制根结点

  • 递归复制左子树
  • 递归复制右子树 

代码实现

int Copy(BiTree T, BiTree& NewT)
{if (T == NULL){NewT = NULL;return 0;//如果是空树,返回0}else{NewT = new BiTNode; NewT->data = T->data;//复制结点数据Copy(T->lchild, NewT->lchild);//递归复制左子树Copy(T->rchild, NewT->rchild);//递归复制右子树}
}
 计算二叉树深度
  • 如果是空树,则深度为0;
  • 否则,递归计算左子树的深度记为m,递归计算右子树的深度记为n,二叉树的深度则为m与n的较大者加1。 

代码实现

int Depth(BiTree T) {if (T == NULL)return 0;else {m = Depth(T->lchild);//求左子树的深度n = Depth(T->rchild);//求右子树的深度if (m > n)return (m + 1);else      return (n + 1);}
}
 计算二叉树结点总数
  •  如果是空树,则结点个数为0;
  • 否则,结点个数为左子树的结点个数+右子树的结点个数再+1。

代码实现

int NodeCount(BiTree T) {if (T == NULL)return 0;else return NodeCount(T->lchild) + NodeCount(T->rchild) + 1;
}

计算二叉树叶子结点数

  • 如果是空树,则叶子结点个数为0;
  • 否则,为左子树的叶子结点个数+右子树的叶子结点个数。 

代码实现

int LeadCount(BiTree T) {if (T == NULL) return 0;if (T->lchild == NULL && T->rchild == NULL)return 1;//如果是叶子结点返回1elsereturn LeafCount(T->lchild) +LeafCount(T->rchild);
}

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

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

相关文章

VR全景摄影的拍摄和编辑软件推荐

随着虚拟现实技术的不断进步,VR全景摄影逐渐成为商业、娱乐和教育等多个领域中的重要工具。通过专业的设备与软件,摄影师能够创作出沉浸式的360度全景作品,为观众提供身临其境的视觉体验。在这篇文章中,我们将介绍VR全景摄影的相关…

(接口测试)day01接口测试理论 http理论 接口测试流程 接口文档解析

一.接口测试理论 1.接口和接口测试 服务器为客户端开了一个验证接口(接口本质:函数方法)客户端向服务器传送的消息可以相当于函数的参数,接口是用来让客户端传递数据的 接口:相当于开了一个通道 当服务器要给客户端响…

yjs机器学习常见算法01——KNN(K—近邻算法)

1.K—近邻算法 的含义: 简单来说就是通过你的邻居的“类别”,来推测你的“类别” 定义:如果一个样本在特征空间中的k个最相似(即特征空间中最临近)的样本中大多数属于某一类别,则该样本也属于这个类别。 2.…

猫头虎分享:什么是 ChatGPT 4o Canvas?

猫头虎是谁? 大家好,我是 猫头虎,猫头虎技术团队创始人,也被大家称为猫哥。我目前是COC北京城市开发者社区主理人、COC西安城市开发者社区主理人,以及云原生开发者社区主理人,在多个技术领域如云原生、前端…

独家创作YOLOv8韭菜检测系统(可以重新训练,yolov8模型,从图像、视频和摄像头三种路径识别检测)

1.简介:资源包含可视化的韭菜检测系统,可检测图片和视频当中出现的韭菜,以及自动开启摄像头,进行韭菜检测。基于最新的YOLO-v8训练的韭菜检测模型和完整的python代码以及韭菜的训练数据,下载后即可运行。 2.文件夹介绍…

怎么找矩阵系统,怎么源码搭建,源头技术开发需要哪些支持

一、引言 在进行矩阵系统源码搭建时,选择合适的工具至关重要。正确的工具选择不仅可以提高开发效率,还能确保系统的稳定性、可扩展性和性能。本文将探讨在矩阵系统源码搭建过程中如何选择合适的工具。 二、前端开发工具选择 前端框架 React:由…

【智能大数据分析 | 实验三】Storm实验:实时WordCountTopology

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈智能大数据分析 ⌋ ⌋ ⌋ 智能大数据分析是指利用先进的技术和算法对大规模数据进行深入分析和挖掘,以提取有价值的信息和洞察。它结合了大数据技术、人工智能(AI)、机器学习(ML&a…

手机、固话号码想要认证,需要显示企业名称该怎么设置?

在现如今激烈竞争的商业环境中,依然有越来越多的企业意识到品牌的力量与价值,作为吸引客户关注、打造客户第一印象的关键环节。如何让企业外呼号码展示品牌与企业名称就变得格外关键。 那么手机、固话号码申请号码品牌认证究竟是什么?申请的…

使用CSS Flexbox创建简洁时间轴

使用CSS Flexbox创建简洁时间轴 在网页设计中,时间轴是一种常见且有效的方式来展示事件的顺序和进程。本文将介绍如何使用CSS Flexbox创建一个简洁优雅的时间轴,无需复杂的JavaScript代码。 基本HTML结构 首先,我们需要创建基本的HTML结构: html复制<div class"ti…

IT招聘乱象的全面分析

近年来&#xff0c;IT行业的招聘要求似乎越来越苛刻&#xff0c;甚至有些不切实际。许多企业在招聘时&#xff0c;不仅要求前端工程师具备UI设计能力&#xff0c;还希望后端工程师精通K8S服务器运维&#xff0c;更有甚至希望研发经理掌握所有前后端框架和最新开发技术。这种招聘…

AI大模型是怎么运作的?深入解析

在当今这个日新月异的科技时代&#xff0c;人工智能&#xff08;AI&#xff09;如同一位隐形的助手&#xff0c;悄然渗透进我们生活的方方面面&#xff0c;其影响力日益显著。这位“隐形助手”背后的工作原理究竟是怎样的呢&#xff1f;接下来&#xff0c;本文将从AI的基本原理…

随机多智能体系统中的自然策略能力

本文探讨了在随机多智能体系统中采用自然策略进行PATL及PATL逻辑的模型检验问题。研究发现&#xff0c;当活跃联盟被限于确定性策略时&#xff0c;NatPATL的模型检验问题是NP完全的&#xff1b;在同样的限制条件下&#xff0c;NatPATL的复杂度则为2NEXPTIME。若不限制策略类型&…

2024全面大模型学习指南

前言 随着人工智能技术的迅猛发展&#xff0c;大模型&#xff08;Large Models&#xff09;已成为这一领域的新宠。从GPT系列到BERT&#xff0c;再到各类变体&#xff0c;大模型以其强大的能力吸引了无数开发者和研究者的目光。那么&#xff0c;作为一个零基础的学习者&#x…

2024 年 04 月编程语言排行榜,PHP 排名创新低?

编程语言的流行度总是变化莫测&#xff0c;每个月的排行榜都揭示着新的趋势。2024年4月的编程语言排行榜揭示了一个引人关注的现象&#xff1a;PHP的排名再次下滑&#xff0c;创下了历史新低。这种变化对于PHP开发者和整个技术社区来说&#xff0c;意味着什么呢&#xff1f; P…

ChatGPT国内中文版镜像网站整理合集(2024/10/06)

一、GPT中文镜像站 ① yixiaai.com 支持GPT4、4o以及o1&#xff0c;支持MJ绘画 ② chat.lify.vip 支持通用全模型&#xff0c;支持文件读取、插件、绘画、AIPPT ③ AI Chat 支持GPT3.5/4&#xff0c;4o以及MJ绘画 1. 什么是镜像站 镜像站&#xff08;Mirror Site&#xff…

LLMs训练避坑帖——如何高效 LLMs pretrain?

LLM训练-pretrain 这篇文章介绍下如何从零到一进行 pretrain 工作。 类似的文章应该有很多&#xff0c;不同的地方可能在于&#xff0c;我并不会去分析 pretrain 阶段的核心技术&#xff0c;而是用比较朴素的语言来描述这个大工程的每一块砖瓦。我的介绍偏方法论一些&#xf…

服务器信息安全可视化:增强风险监测

通过图扑可视化技术&#xff0c;将服务器的安全状态以图形化方式展示&#xff0c;帮助安全团队实时监控潜在威胁&#xff0c;提高快速响应能力&#xff0c;保障数据和系统的安全性与稳定性。

【MATLAB源码-第248期】基于matlab的EMD算法+ICA算法轴承故障分析。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 经验模态分解&#xff08;EMD&#xff09;与轴承故障识别 EMD的基本原理 EMD 是一种自适应的信号分解技术&#xff0c;最初由 Huang 等人在 1998 年提出&#xff0c;旨在分析非线性和非平稳信号。传统的信号处理方法通常假设…

绘制YOLOv11模型在训练过程中,精准率,召回率,mAP_0.5,mAP_0.5:0.95,以及各种损失的变化曲线

一、本文介绍 本文用于绘制模型在训练过程中,精准率,召回率,mAP_0.5,mAP_0.5:0.95,以及各种损失的变化曲线。用以比较不同算法的收敛速度,最终精度等,并且能够在论文中直观的展示改进效果。支持多文件的数据比较。 专栏目录:YOLOv11改进目录一览 | 涉及卷积层、轻量化…

E41.【C语言】练习:斐波那契函数的空间复杂度的计算及函数调用分析

1.题目 求下列代码的时间复杂度 long long f(size_t n) {if(n < 3)return 1;return f(n-1) f(n-2); } 2.解 显然是递归算法(递归讲解见35.【C语言】详解函数递归),可以画个二叉树分析 Fib嵌套函数调用细则的分析 进入f(n),返回f(n-1)f(n-2),注意:一次只能调用一个函数…