数据结构_第十一关:二叉树的链式结构

news2025/6/14 14:25:44

目录

1.二叉树链式结构的实现

1.1前置说明

1.2二叉树的遍历

1.3二叉树遍历的实现:

1)先序遍历、中序遍历、后续遍历代码如下

2)层序遍历:

1.4结点个数以及高度的计算

1)求二叉树的总节点:

2)求叶子节点的个数

3)求树的深度/高度

4)求第K层的结点数 k>=1

5)二叉树查找值未x的节点 

2.二叉树的基础OJ题练习


1.二叉树链式结构的实现

1.1前置说明

此次二叉树链式结构的讲解先不进行增删查改,之后学完c++再进一步学习

事实上,二叉树的增删查改没有价值,
学习二叉树的意义是:再其基础上完成对搜索二叉树的学习

搜索二叉树:左孩子比父节点小,右孩子比父节点大

搜索二叉树学习完之后,就到了对平衡二叉树(AVL树+红黑树)的学习,
这里就不多介绍了(绝不是因为我现在也不太懂^.^)

1.2二叉树的遍历

学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉 树中的节点进行相应的操作,并且每个节点只操作一次。访问结点所做的操作依赖于具体的应用问题。 遍历 是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础

四种遍历方法:

  • 先序遍历:根、左子树、右子树
  • 中序遍历:左子树、跟、右子树
  • 后序遍历:左子树、右子树、跟
  • 层序遍历:从第一层开始、每层从左到右,一层一层的走

前序遍历结果:1 2 3 4 5 6

中序遍历结果:3 2 1 5 4 6

后序遍历结果:3 2 5 6 4 1

层次遍历结果:1 2 4 3 5 6

练习:请写出下面的前序/中序/后序/层序遍历

 选择题:

1.某完全二叉树按层次输出(同一层从左到右)的序列为 ABCDEFGH 。

该完全二叉树的前序序列为( )
A ABDHECFG
B ABCDEFGH
C HDBEAFCG
D HDEBFGCA


2.二叉树的先序遍历和中序遍历如下:先序遍历:EFHIGJK;中序遍历:HFIEJKG.

则二叉树根结点为()
A E
B F
C G
D H


3.设一课二叉树的中序遍历序列:badce,后序遍历序列:bdeca,则二叉树前序遍历序列

为(  )
A adbce
B decab
C debac
D abcde


4.某二叉树的后序遍历序列与中序遍历序列相同,均为 ABCDEF ,则按层次输出

(同一层从左到右)的序列为
A FEDCBA 
B CBAFED
C DEFCBA
D ABCDEF

答案:1.A         2.A        3.D        4.A

1.3二叉树遍历的实现:

在实现前,我们先要建立一个树,因为我们暂时不学习二叉树的建立,

所以我们直接手动建立如下图的二叉树

手动建立如下:

#include<stdio.h>
#include<stdlib.h>

typedef int BTDataType;
typedef struct BinaryTreeNode
{
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;

int main()
{
	BTNode* root;

	BTNode* n1 = BuyBTNode(1);
	BTNode* n2 = BuyBTNode(2);
	BTNode* n3 = BuyBTNode(3);
	BTNode* n4 = BuyBTNode(4);
	BTNode* n5 = BuyBTNode(5);
	BTNode* n6 = BuyBTNode(6);
	n1->left = n2;
	n1->right = n4;
	n2->left = n3;
	n4->left = n5;
	n4->right = n6;

    return 0;
}

1)先序遍历、中序遍历、后续遍历代码如下

因为他们的代码只是遍历顺序不同,所以就放一起了

//前序遍历
void PrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		//printf("NULL ");
		return;
	}

	printf("%d ", root->data);
	PrevOrder(root->left);
	PrevOrder(root->right);
}
//中序遍历
void InOrder(BTNode* root)
{
	if (root == NULL)
	{
		//printf("NULL ");
		return;
	}
	PrevOrder(root->left);
	printf("%d ", root->data);
	PrevOrder(root->right);
}
//后续遍历
void PostOrder(BTNode* root)
{
	if (root == NULL)
	{
		//printf("NULL ");
		return;
	}
	PrevOrder(root->left);
	PrevOrder(root->right);
	printf("%d ", root->data);
}

2)层序遍历:

  1. 首先,将二叉树的根节点放入一个队列中

  2. 从队列的头部取出一个元素(记为当前元素cur),将cur的左孩子作为新节点放入队列尾部,再将cur的右孩子作为新节点放入队列尾部。因为队列是先进先出的,所以这样处理后,下一次取出来的就是左孩子,再下一次取出来的就是右孩子了。

  3. 重复步骤2,直到队列为空为止。

void LevelOrder(BTNode* root) 
{
	if (root == NULL) 
		return;

	BTNode* queue[1000];   // 定义队列,最多存放1000个节点

	int head = 0, tail = 0;
	queue[tail++] = root;
	while (head < tail) 
	{
		BTNode* curNode = queue[head++];   // 出队

		printf("%d ", curNode->data);

		if (curNode->left != NULL)
			queue[tail++] = curNode->left;    // 左孩子入队

		if (curNode->right != NULL)
			queue[tail++] = curNode->right;   // 右孩子入队
	}
}

1.4结点个数以及高度的计算

因为二叉树适合用递归的方式来计算,所以不论是上面的遍历二叉树还是其他计算,他们的代码都是用递归来实现的

1)求二叉树的总节点:

有两种方法:

  1. 定义一个全局变量size,在每次计算前都要手动将其置为0
  2. 直接用递归来进行计算

方法1:

int size = 0;//定义全局变量
void TreeSize1(BTNode* root)
{
	if (root == NULL)
		return;

	size++;
	TreeSize1(root->left);
	TreeSize1(root->right);
}

//使用时:
int main()
{
    size = 0;  //size是全局变量,每次使用前都需要手动置0,否则会在之前的基础上再加
	TreeSize1(n1);
	printf("TreeSize1:%d\n", size);

	TreeSize1(n1);
	printf("TreeSize1(size未置0):%d\n", size);

	size = 0;
	TreeSize1(n1);
	printf("TreeSize1(重新将size置0):%d\n", size);
    
    return 0;
}

结果如下: 

 方法二:直接用递归来求:

int TreeSize2(BTNode* root)
{
	return root == NULL ? 0 : TreeSize2(root->left) + TreeSize2(root->right) + 1;
}

//使用
int main()
{
    printf("TreeSize2:%d\n", TreeSize2(n1));
	printf("TreeSize2:%d\n", TreeSize2(n1));
	printf("TreeSize2:%d\n", TreeSize2(n1));
    
    return 0;
}

2)求叶子节点的个数

int TreeLeafSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	if (root->left == NULL && root->right == NULL)
	{
		return 1;
	}
	return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}

3)求树的深度/高度

int TreeHeight(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	//保留算出的数据,防止重复计算比较
	int leftHeight = TreeHeight(root->left);
	int rightHeight = TreeHeight(root->right);

	return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}

注意这里写的时候不要像下面那样直接返回,

return   TreeLeafSize(root->left) > TreeLeafSize(root->right) ? 
            TreeLeafSize(root->left) + 1 : TreeLeafSize(root->right) + 1;

这种写法十分浪费资源,会有很多重复的计算,导致效率特别低

正确的写法是先将其保存起来,再进行比较和返回递归

4)求第K层的结点数 k>=1

int TreeKLevelSize(BTNode* root, int k)
{
	if (root == NULL)
		return 0;

	if (k == 1)
		return 1;

	// k > 1 子树的k-1
	return TreeKLevelSize(root->left, k - 1)+ TreeKLevelSize(root->right, k - 1);
}

5)二叉树查找值未x的节点 

BTNode* TreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
		return NULL;

	if (root->data == x)
		return root;

	BTNode* ret1 = TreeFind(root->left, x);
	if (ret1)
		return ret1;

	BTNode* ret2 = TreeFind(root->right, x);
	if (ret2)
		return ret2;
}

2.二叉树的基础OJ题练习

(思路和代码下一关里面讲)

  • 1. 单值二叉树。                        OJ题链接
  • 2. 检查两颗树是否相同             OJ题链接
  • 3. 对称二叉树。                        OJ题链接
  • 4. 另一颗树的子树。                 OJ题链接

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

阿里张勇:所有行业都值得用大模型重新做一遍!

‍数据智能产业创新服务媒体——聚焦数智 改变商业“2023阿里云峰会”于4月11日在北京国际会议中心隆重召开&#xff0c;本次峰会以" 与实俱进 为创新提速&#xff01;"为主题&#xff0c;阿里巴巴集团董事会主席兼首席执行官张勇、阿里云智能集团首席技术官周靖人、…

Python机器学习:适合新手的8个项

再多的理论也不能代替动手实践。教科书和课程会让你误以为精通&#xff0c;因为材料就在你面前。但当你尝试去应用它时&#xff0c;可能会发现它比看起来更难。而「项目」可帮助你快速提高应用的 ML 技能&#xff0c;同时让你有机会探索有趣的主题。此外&#xff0c;你可以将项…

java mysql高校教学成果管理系统dzkfY3程序

1.用户管理模块&#xff1a; 该模块包括注册用户管理和系统用户管理&#xff0c;系统用户主要是普通管理员&#xff0c;对用户信息进行管理&#xff0c;只有注册用户才可在该系统上进行相应的操作。用户对个人信息可进行修改&#xff1b;管理员可对自己的个人信息进行维护&…

Java线程系列详解

一&#xff0c;基本概念 进程&#xff1a; 程序是计算机指令的集合&#xff0c;它以文件形式存储在磁盘上&#xff0c;而进程就是一个执行中的程序&#xff0c;而每一个进程都有其独立的内存空间和系统资源。线程&#xff1a; 线程运行在进程中&#xff0c;不能独立存在。线程…

2019年 团体程序设计天梯赛——题解集

前言&#xff1a; Hello各位童学大家好&#xff01;&#x1f60a;&#x1f60a;&#xff0c;茫茫题海你我相遇即是缘分呐&#xff0c;或许日复一日的刷题已经让你感到疲惫甚至厌倦了&#xff0c;但是我们真的真的已经达到了我们自身极限了吗&#xff1f;少一点自我感动&#xf…

城乡供水一体化信息化系统-城乡供水一体化

建设方案 城乡供水一体化信息化系统是运用云计算、大数据等信息化手段&#xff0c;借助在线监测设备&#xff0c;并依托“供水信息化平台”&#xff0c;实时感知供水系统的运行状态&#xff0c;实现对农村供水工程远程监控、在线监测、实时预警、智慧监管。 系统功能 水源地监测…

【 初识 Spring MVC 程序开发 】

文章目录一、什么是 Spring MVC二、什么是 MVC三、MVC 和 Spring MVC 的关系四、为什么要学 Spring MVC五、怎么学 Spring MVC六、Spring MVC 创建和连接一、什么是 Spring MVC Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架&#xff0c;从⼀开始就包含在 Spring 框…

搜索算法(一) 深度优先搜索 dfs

一、搜索算法 包括深度优先搜索算法和广度优先搜索算法&#xff0c;用于树或图等结构中进行搜索。 二、深度优先搜索 深度优先算法会尽可能深地搜索树的分支。当节点v的所在边都己被探寻过&#xff0c;搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源…

全网最详细,Jmeter性能测试-性能基础详解,终成测试卷王(一)

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 发起请求 发起HTTP…

电脑自动录屏软件哪个好用 电脑自动录屏怎么设置

录屏是很多工作都需要进行的操作&#xff0c;很多会议、培训课程、PPT等都可能需要通过屏幕录制的方式来进行分享。但是目前市面上的录屏软件很多&#xff0c;想找到使用便捷且高效的软件并不容易。今天就来分享一下电脑自动录屏软件哪个好用&#xff0c;电脑自动录屏怎么设置。…

条码控件Aspose.BarCode入门教程(5):用Java 生成和扫描二维码

Aspose.BarCode for .NET 是一个功能强大的API&#xff0c;可以从任意角度生成和识别多种图像类型的一维和二维条形码。开发人员可以轻松添加条形码生成和识别功能&#xff0c;以及在.NET应用程序中将生成的条形码导出为高质量的图像格式。 Aspose API支持流行文件格式处理&am…

学习数据结构第4天(线性表的顺序表示)

线性表的顺序表示顺序表的定义顺序表的基本操作顺序表的定义 线性表的顺序存储又称顺序表。顺序表是在计算机内存中以数组的形式保存的线性表&#xff0c;线性表的顺序存储时指用一组地址连续的存储单元&#xff0c;依次存储线性表中的各个元素。因此线性表中任一数据元素都可…

60行代码出炫酷效果之 python语音控制电脑壁纸切换

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 电脑大家有吧&#xff01;手大家有吧&#xff01;今天&#xff01;&#xff01; 就由我带领大家用区区60行代码打造一款语音壁纸切换器程序&#xff01;&#xff01;&#xff01; 单纯的桌面有时候会让人觉得单调&#xff0c…

vue.js实现带表情评论功能前后端实现(仿B站评论)

文章目录学习链接效果图后台建表评论表&#xff08;重要&#xff09;用户表实体类CommentUserCommentDTO&#xff08;重要&#xff09;WebConfig配置配置跨域和静态资源文件夹Mybatisplus相关类MyBatisPlusConfig 配置分页插件CommentMapperCommentMapper.xml&#xff08;非常重…

git 将其它分支的文件检出到工作区

主要是使用如下命令&#xff1a; git checkout [-f|--ours|--theirs|-m|--conflict<style>] [<tree-ish>] [--] <pathspec>…​覆盖与 pathspec 匹配的文件的内容。当没有给出<tree-ish> (通常是一个commit)时&#xff0c;用 index 中的内容覆盖工作树…

高频电流探头示波器电流探头的功能检验和消磁操作

高频电流探头运用了成熟的霍尔效应技术并与示波器接口相结合。主要特点包括&#xff1a;分芯结构&#xff0c;简便地连接电路&#xff1b;AC / DC测量能力&#xff1b;精度1%5mV&#xff1b;连接的仪器上直接显示读数。 功能检验&#xff1a; 1、探头连接示波器&#xff1b; 2…

OpenAI Embedding:基于人工智能的搜索新篇章

theme: orange 本文正在参加「金石计划」 Embedding模型在许多应用场景中都有广泛的应用。在OpenAI中&#xff0c;文本嵌入技术主要用于衡量文本字符串之间的相关性。 什么是Embedding 嵌入(Embeddings)是一种将离散变量表示为连续向量的方法。它在机器学习中起到了不可或缺的作…

字节分享的软件测试《面试笔记》文档,让我直呼卧槽卧槽

我有一个朋友&#xff08;真是朋友&#xff0c;不是我啊&#xff09;&#xff0c;前几年环境好的时候入的行&#xff0c;那时候软件测试的要求真的很低&#xff0c;他那时好像是报了个班&#xff0c;然后入门的&#xff0c;但学的都是些基础&#xff0c;自动化涉及了一点&#…

天坑,后悔进那外包啊......

关于计算机专业应届生毕业之后会遇到的就业问题&#xff0c;网上已经有许多的套路&#xff0c;实际上许多人在选择专业的时候并没有考虑到之后的就业方向&#xff0c;甚至于自己所学的专业面向的工作岗位都不是特别清楚。计算机专业毕业大概率是要做程序员的&#xff0c;而目前…

【Java EE】-多线程编程(九) 锁策略CAS锁优化

作者&#xff1a;学Java的冬瓜 博客主页&#xff1a;☀冬瓜的主页&#x1f319; 专栏&#xff1a;【JavaEE】 分享&#xff1a; 主要内容&#xff1a;乐观锁VS悲观锁、轻量级锁VS重量级锁、自旋锁VS挂起等待锁、互斥锁VS读写锁、公平锁VS非公平锁、可重入锁VS不可重入锁。CAS实…