数据结构(初阶6)---二叉树(遍历——递归的艺术)(详解)

news2024/11/28 1:03:44

二叉树的遍历与练习

  • 一.二叉树的基本遍历形式
    • 1.前序遍历(深度优先遍历)
    • 2.中序遍历(深度优先遍历)
    • 3.后序遍历(深度优先遍历)
    • 4.层序遍历!!(广度优先遍历)
  • 二.二叉树的leetcode小练习
    • 1.判断平衡二叉树
      • 1)正常解法
      • 2)优化解法
    • 2.对称二叉树

通过上一篇文章,我们初识了我们的二叉树
二叉树初识
那么接下来我们就要深入去理解二叉树的部分知识了,显然这只是在二叉树家族中迈出的一小步qwq,入门。

一.二叉树的基本遍历形式

我们先建立一棵伪树,方便我们后续的使用:请添加图片描述

int main()
{
	BinaryTree p1;
	BinaryTree p2;
	BinaryTree p3;
	BinaryTree p4;
	BinaryTree p5;
	BinaryTree p6;
	p1.left = &p2;
	p1.right = &p3;
	p2.left = NULL;
	p2.right = &p4;
	p3.left = &p5;
	p3.right = NULL;
	p4.left = NULL;
	p4.right = &p6;
	p6.left = NULL;
	p6.right = NULL;
	p5.left = NULL;
	p5.right = NULL;
	p1.val = 'A';
	p2.val = 'B';
	p3.val = 'C';
	p4.val = 'D';
	p5.val = 'E';
	p6.val = 'F';
}

1.前序遍历(深度优先遍历)

前序遍历的本质,就是根节点->左孩子->右孩子。并且通过递归调用的方式去实现。
请添加图片描述

void treefront(BinaryTree* p)//前序遍历
{
	if (p == NULL)
	{
		printf("NULL ");
		return;
	}
	printf("%c ", p->val);
	treefront(p->left);
	treefront(p->right);

}

2.中序遍历(深度优先遍历)

同理,中序遍历的本质就是左孩子->根节点->右孩子
如:
请添加图片描述

void treemid(BinaryTree* p)//中序遍历
{
	if (p == NULL)
	{
		printf("NULL ");
		return;
	}
	treemid(p->left);
	printf("%c ", p->val);
	treemid(p->right);

}

3.后序遍历(深度优先遍历)

同理,后序遍历的本质就是:左孩子->右孩子->根节点
如:
请添加图片描述

void treebehind(BinaryTree* p)//后序遍历
{
	if (p == NULL)
	{
		printf("NULL ");
		return;
	}
	treebehind(p->left);
	treebehind(p->right);
	printf("%c ", p->val);
}

4.层序遍历!!(广度优先遍历)

层序遍历与以上三种遍历方式完全不同,他没有使用递归的思想,而是去使用了迭代的方法:
请添加图片描述
这里我们将使用我们先前学到的循环队列的数据结构去完成二叉树的层序遍历
逻辑如下:
运用队列的先进先出的特点
1.我们先塞入第一个根节点,
2.我们取出队列排头的节点的时候,自动往队列里面添加两个他的儿子节点
3.当队列里面为空的时候,我们就完成了一次层序遍历
请添加图片描述
接下来我们进行代码实现:
1.伪树

int main()
{
	BinaryTree p1;
	BinaryTree p2;
	BinaryTree p3;
	BinaryTree p4;
	BinaryTree p5;
	BinaryTree p6;
	p1.left = &p2;
	p1.right = &p3;
	p2.left = NULL;
	p2.right = &p4;
	p3.left = &p5;
	p3.right = NULL;
	p4.left = NULL;
	p4.right = &p6;
	p6.left = NULL;
	p6.right = NULL;
	p5.left = NULL;
	p5.right = NULL;
	p1.val = 'A';
	p2.val = 'B';
	p3.val = 'C';
	p4.val = 'D';
	p5.val = 'E';
	p6.val = 'F';
}

2.层序遍历

#pragma once
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef BinaryTree* QueueDataType;
typedef struct CirQueue
{
	QueueDataType* q;
	int front;
	int rear;
	int capacity;
}CirQueue;


QueueDataType Cirqueuefront(CirQueue* p1)
{
	return *((p1->q)+(p1->front));
}

CirQueue* CirQueueCreate(CirQueue* p,size_t x)
{
	p = (CirQueue*)malloc(sizeof(CirQueue));
	p->q = (QueueDataType*)(malloc(sizeof(QueueDataType) * x));
	p->capacity = x;
	p->front = 0;
	p->rear = 0;
}
int isCirQueueEmpty(CirQueue* p)
{
	if (p->front == p->rear)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
int isCirQueueFull(CirQueue* p)
{
	if ((p->rear+1) % p->capacity == p->front)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
void CirQueuePop(CirQueue* p)
{
	if (!isCirQueueEmpty(p))
	{
		p->front=(p->front+1)%p->capacity;
	}
	else
	{
		return;
	}
}
void CirQueuePush(CirQueue* p,QueueDataType x)
{
	if (isCirQueueFull(p))
	{
		return;
	}
	else
	{
		*(p->q + p->rear) = x;
		p->rear = (p->rear + 1) % p->capacity;
	}
}

void treeseq(BinaryTree* p)//层序遍历
{
	CirQueue* que=NULL;
	que = CirQueueCreate(que, 20);
	CirQueuePush(que, p);
	while (!isCirQueueEmpty(que))
	{
		if (Cirqueuefront(que) != NULL)
		{
			printf("%c ", Cirqueuefront(que)->val);
			CirQueuePush(que, Cirqueuefront(que)->left);
			CirQueuePush(que, Cirqueuefront(que)->right);
		}
		else
		{
			printf("NULL ");
		}
		CirQueuePop(que);
	}
}

在这里插入图片描述

二.二叉树的leetcode小练习

1.判断平衡二叉树

在这里插入图片描述
平衡二叉树:当二叉树的每一个节点的两个子树的深度的差的绝对值小于1,则称为平衡二叉树。

1)正常解法

1.先创造求深度函数

int depthtree(struct TreeNode* root)
{
    if(root==NULL)
    {
        return 0;
    }
    int leftdepth=depthtree(root->left);
    int rightdepth=depthtree(root->right);
    return 1+(leftdepth>rightdepth?leftdepth:rightdepth);
}

再通过分解子问题
求大树是否为平衡二叉树,我们先求解两个子树是不是平衡二叉树

bool isBalanced(struct TreeNode* root) {
    if(root==NULL)
    {
        return true;
    }
    int left=depthtree(root->left);
    int right=depthtree(root->right);
    bool x=(left-right<=1)&&(left-right>=-1);
    if(!x)
    {
        return false;
    }
    return isBalanced(root->left)&&isBalanced(root->right);
}

2)优化解法

刚刚的那种解法是一种低效的解法,通过前序遍历我们进行了很多次重复的计算。
所以我们考虑一下,是否可以使用后序遍历,
先快速来到底部,从底部向上走,而每一次的树的深度就可以直接将当前子树的高度++即可

bool _isBalanced(struct TreeNode* root,int* pdepth)
{
    
    if(root==NULL)
    {
        return true;
    }
    int depth_left=0;
    int depth_right=0;
    if(!_isBalanced(root->left,&depth_left))
    {
        return false;
    }
    if(!_isBalanced(root->right,&depth_right))
    {
        return false;
    }
    if(abs(depth_right-depth_left)>1)
    {
        return false;
    }
    *pdepth=1+(depth_right>depth_left?depth_right:depth_left);
    return true;
}
bool isBalanced(struct TreeNode* root) {
    int depth=0;
    return _isBalanced(root,&depth);
}

在这里插入图片描述

这样子我们只需要遍历n次,时间复杂度O(n)即可解决问题

2.对称二叉树

在这里插入图片描述
通过相反的遍历比较,可以得出是否为二叉树

bool issame(struct TreeNode* p1,struct TreeNode* p2)
{
    if(p1==NULL&&p2==NULL)
    {
        return true;
    }
    else if((p1==NULL&&p2!=NULL)||(p1!=NULL&&p2==NULL))
    {
        return false;
    }
    return (p1->val==p2->val)&&issame(p1->left,p2->right)&&issame(p2->left,p1->right);
}
bool isSymmetric(struct TreeNode* root) {
    if(root==NULL)
    {
        return true;
    }
    return issame(root->left,root->right);
    
}

在这里插入图片描述

ps:创作不易,恳请留一个赞吧

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

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

相关文章

spring boot2.7集成OpenFeign 3.1.7

1.Feign Feign是一个声明式web服务客户端。它使编写web服务客户端更容易。要使用Feign&#xff0c;请创建一个接口并对其进行注释。它具有可插入注释支持&#xff0c;包括Feign注释和JAX-RS注释。Feign还支持可插拔编码器和解码器。Spring Cloud增加了对Spring MVC注释的支持&…

基于Redis内核的热key统计实现方案|得物技术

一、Redis热key介绍 Redis热key问题是指单位时间内&#xff0c;某个特定key的访问量特别高&#xff0c;占用大量的CPU资源&#xff0c;影响其他请求并导致整体性能降低。而且&#xff0c;如果访问热key的命令是时间复杂度较高的命令&#xff0c;会使得CPU消耗变得更加严重&…

CTF-Hub SQL 报错注入(纯手动注入)

​ 当输入1时&#xff0c;发现只有查询正确&#xff0c;基本上可以判断出没有回显 开始注入(工具hackerBar) 题目是报错注入&#xff0c;方向就比较明显&#xff0c;大致说一下用到的函数和原理。 常见报错注入函数&#xff1a; 通过 floor() 报错注入通过 extractValue() …

Elasticsearch中的节点(比如共20个),其中的10个选了一个master,另外10个选了另一个master,怎么办?

大家好&#xff0c;我是锋哥。今天分享关于【Elasticsearch中的节点&#xff08;比如共20个&#xff09;&#xff0c;其中的10个选了一个master&#xff0c;另外10个选了另一个master&#xff0c;怎么办&#xff1f;】面试题。希望对大家有帮助&#xff1b; Elasticsearch中的节…

linux安装mysql8.0.40

一、下载MySQL安装包 1.查看glibc版本 rpm -qa | grep glibc 2.到mysql官网下载安装包 ​ 二、解压安装 1.上传压缩包纸/usr/local 目录下&#xff0c;解压&#xff1a; tar -xvf mysql-8.0.40-linux-glibc2.17-x86_64.tar.xz 2.重命名&#xff1a; mv mysql-8.0.40-linux-…

【大数据学习 | Spark-Core】RDD的五大特性(包含宽窄依赖)

分析一下rdd的特性和执行流程 A list of partitions 存在一系列的分区列表A function for computing each split 每个rdd上面都存在compute方法进行计算A list of dependencies on other RDDs 每个rdd上面都存在一系列的依赖关系Optionally, a Partitioner for key-value RDDs…

在 Taro 中实现系统主题适配:亮/暗模式

目录 背景实现方案方案一&#xff1a;CSS 变量 prefers-color-scheme 媒体查询什么是 prefers-color-scheme&#xff1f;代码示例 方案二&#xff1a;通过 JavaScript 监听系统主题切换 背景 用Taro开发的微信小程序&#xff0c;需求是页面的UI主题想要跟随手机系统的主题适配…

【C语言】int *p[ ] 与 int (*p)[ ] 的区分辨析

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C语言 文章目录 &#x1f4af;前言&#x1f4af;基本概念&#xff1a;数组与指针&#x1f4af;理解 int *p[10] 与 int (*p)[10]1. int *p[10]&#xff1a;存放指针的数组2. int (*p)[10]&#xff1a;指向数组的指针 …

Vue3 el-table 默认选中 传入的数组

一、效果&#xff1a; 二、官网是VUE2 现更改为Vue3写法 <template><el-table:data"tableData"border striperow-key"id"ref"tableRef":cell-style"{ text-align: center }":header-cell-style"{background: #b7babd…

MT6769/MTK6769核心板规格参数_联发科安卓主板开发板方案

MT6769安卓核心板具有集成的蓝牙、FM、WLAN和GPS模块&#xff0c;是一个高度集成的基带平台&#xff0c;结合了调制解调器和应用处理子系统&#xff0c;以支持LTE/LTE-A和C2K智能手机应用。 该芯片集成了两个工作频率高达2.0GHz的ARMCortex-A75内核、六个工作频率高达1.70GHz的…

在Excel中处理不规范的日期格式数据并判断格式是否正确

有一个Excel表&#xff0c;录入的日期格式很混乱&#xff0c;有些看着差不多&#xff0c;但实际多一个空格少一个字符很难发现&#xff0c;希望的理想格式是 1980-01-01&#xff0c;10位&#xff0c;即&#xff1a;“YYYY-mm-dd”&#xff0c;实际上数据表中这样的格式都有 19…

flask请求头回显的学习和探究如何进行错误页面污染回显

请求头 首先我们要了解一些flask的请求和响应是利用了什么。 flask的请求和响应主要利用了werkzeug&#xff0c;那么我们就要先了解一下什么是werkzeug&#xff0c;其结构又是什么。 werkzeug是一个基于python开发的一个web工具包&#xff0c;其是flask的核心组件之一。其功能…

【Unity踩坑】Unity中父对象是非均匀缩放时出现倾斜或剪切现象

The game object is deformed when the parent object is in non-uniform scaling. 先来看一下现象 有两个Cube, Cube1&#xff08;Scale2,1,1)&#xff0c;Cube2&#xff08;Scale1,1,1&#xff09; 将Cube2拖拽为Cube2的子对象。并且将position设置为&#xff08;-0.6,1,0&a…

uni-app 蓝牙开发

一. 前言 Uni-App 是一个使用 Vue.js 开发&#xff08;所有&#xff09;前端应用的框架&#xff0c;能够编译到 iOS、Android、快应用以及各种小程序等多个平台。因此&#xff0c;如果你需要快速开发一款跨平台的应用&#xff0c;比如在 H5、小程序、iOS、Android 等多个平台上…

解决SSL VPN客户端一直提示无法连接服务器的问题

近期服务器更新VPN后&#xff0c;我的win10电脑一致无法连接到VPN服务器&#xff0c; SSL VPN客户端总是提示无法连接到服务端。网上百度尝试了各种方法后&#xff0c;终于通过以下设置方式解决了问题&#xff1a; 1、首先&#xff0c;在控制面板中打开“网络和共享中心”窗口&…

spring boot框架漏洞复现

spring - java开源框架有五种 Spring MVC、SpringBoot、SpringFramework、SpringSecurity、SpringCloud spring boot版本 版本1: 直接就在根下 / 版本2:根下的必须目录 /actuator/ 端口:9093 spring boot搭建 1:直接下载源码打包 2:运行编译好的jar包:actuator-testb…

大语言模型LLM的微调代码详解

代码的摘要说明 一、整体功能概述 这段 Python 代码主要实现了基于 Hugging Face Transformers 库对预训练语言模型&#xff08;具体为 TAIDE-LX-7B-Chat 模型&#xff09;进行微调&#xff08;Fine-tuning&#xff09;的功能&#xff0c;使其能更好地应用于生成唐诗相关内容的…

华三(HCL)和华为(eNSP)模拟器共存安装手册

接上章叙述,解决同一台PC上同时部署华三(HCL)和华为(eNSP)模拟器。原因就是华三HCL 的老版本如v2及以下使用VirtualBox v5版本,可以直接和eNSP兼容Oracle VirtualBox,而其他版本均使用Oracle VirtualBox v6以上的版本,所以正常安装HCL模拟器无法和ENSP兼容。 环境及组件:…

Android 15 版本更新及功能介绍

Android 15版本时间戳 Android 15,代号Vanilla Ice Cream(香草冰淇淋),是当下 Android 移动操作系统的最新主要版本。 开发者预览阶段:2024年2月,谷歌发布了Android 15的第一个开发者预览版本(DP1),这标志着新系统开发的正式启动。随后,在3月和4月,谷歌又相继推出了D…

【含开题报告+文档+PPT+源码】基于Spring Boot+Vue的在线学习平台的设计与实现

开题报告 随着互联网的普及和技术的快速发展&#xff0c;网络教育逐渐崭露头角&#xff0c;成为现代教育领域的重要组成部分。网络教育以其灵活性、便捷性和资源共享性&#xff0c;吸引了越来越多的学习者。同时&#xff0c;随着学习者需求的多样化&#xff0c;他们对于在线学…