09 二叉树链式结构

目录

1.链式结构的创建
2.遍历的方式
3.结点数的计算
4.高度的计算
5.第k层的节点个数
6.查找值
7.判断完全二叉树
8,销毁
9.OJ题


1.链式结构

在学习二叉树基本操作前,需要先创建一颗二叉树。为了快速上手,这里手动擦窗机简单的二叉树。等后面再自动创建

typedef int TDataType;
typedef struct BinaryTreeNode
{
	TDataType _data;
	struct BinaryTreeNode* _left;
	struct BinaryTreeNode* _right;
}TNode;
TNode* BuyNode(TDataType data)
{
	TNode* newnode = (TNode*)malloc(sizeof(TNode));
	if (newnode == NULL)
	{
		perror("mallco");
		return NULL;
	}

	//初始化数据
	newnode->_data = data;
	newnode->_left = NULL;
	newnode->_right = NULL;
	return newnode;
}

TNode* CreatBinaryTree()
{
	TNode* node1 = BuyNode(1);
	TNode* node2 = BuyNode(2);
	TNode* node3 = BuyNode(3);
	TNode* node4 = BuyNode(4);
	TNode* node5 = BuyNode(5);
	TNode* node6 = BuyNode(6);

	node1->_left = node2;
	node1->_right = node4;
	node2->_left = node3;
	node4->_left = node5;
	node4->_right = node6;

	return node1;
}

上面的二叉树的图形
在这里插入图片描述

2. 二叉树的遍历

2.1 前序、中序、后续遍历

二叉树遍历是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,每个节点只操作一次。遍历是二叉树最重要的运算之一,也是二叉树上进行其他的运算的基础

前序遍历(Preorder Traversal 先序遍历/先根遍历)
访问根节点的操作发生在遍历其左右子树之前
根节点 左子树 右子树
1 2 3 N N N 4 5 N N 6 N N
N代表空

void PrePrint(TNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}

	printf("%d ", root->_data);
	PrePrint(root->_left);
	PrePrint(root->_right);
}

在这里插入图片描述
在这里插入图片描述

中序遍历(Inorder Traversal)
访问根节点的操作发生在遍历其左右子树之中
N 3 N 2 N 1 N 5 N 4 N 6 N
在这里插入图片描述在这里插入图片描述

前序遍历(Postorder Traversal)
访问根节点的操作发生在遍历其左右子树之后
N N 3 N 2 N N 5 N N 6 4 1
在这里插入图片描述
在这里插入图片描述
递归的条件:
1.子问题
2.返回条件,不然会栈溢出
上面的时间复杂度是O(N),有N个结点要打印N次
空间复杂度是高度O(h),空间可以重复利用,兄弟层用的一个栈帧空间

三种遍历的联系
在没有重复值的前提下
先序遍历可以得到二叉树的根结点,如果有左右子树,可以得到左右子树对应的根节点
中序遍历的根结点分成左右子树
后序遍历的最后一个是二叉树的根节点,再往前可能是右子树的根节点
中序和前序后序任一个联合可以得到整个树的结构,前序和后序确定根,中序分割左右子树
二叉树的先序和后序遍历结果相反,树中每个结点只有一个孩子,只有一个叶子结点,结果就是相反的
在这里插入图片描述

2.2 层序遍历

层序遍历就是从根结点为第1层开始,一层一层向下遍历

思路
可以利用队列先进先出的规则,先将根节点压进去,根节点出来的时候再将左右节点压进去,重复这个过程。这样打印的时候就不会破坏顺序,先进队列的先打印

之前队列的数据类型是int,需要改成结点的指针类型,单纯压入值并不能得到左右结点,所以要压入结点的地址

结构文件

typedef int TDataType;
typedef struct BinaryTreeNode
{
	TDataType _data;
	struct BinaryTreeNode* _left;
	struct BinaryTreeNode* _right;
}TNode;

typedef TNode* DATATYPE;

//节点
typedef struct _Node
{
	DATATYPE data;
	struct _Node* next;
}Node;

//队列
typedef struct _Queue
{
	struct _Node* head;
	struct _Node* tail;
	int size;
}Queue;

函数

void LevelPrint(TNode* root)
{

	Queue que;
	Init(&que);

	if (root != NULL)
	{
		Push(&que, root);
	}

	while (!Empty(&que))
	{
		TNode* top = Front(&que);
		printf("%d ", top->_data);
		Pop(&que);
		if (top->_left != NULL)
		{
			Push(&que, top->_left);
		}
		if (top->_right != NULL)
		{
			Push(&que, top->_right);
		}
		
	}
}

在这里插入图片描述

在这里插入图片描述

首先是队列的结构,队列有一个头节点和尾节点,,为了方便理解,上面的头尾节点没存数据,实际上头尾结点也存数据。头结点的下一个链接到下一个结点的地址,结点里保存了二叉树的根节点地址。先压入头结点入队,出队时释放的是队列结点的指针,并不是二叉树根结点的地址,然后按顺序压入根结点的左右子树地址,直到队列为空结束

3. 结点个数的计算

可以根据上面的遍历所有结点,每次访问一个结点数量加1

int count = 0;
int TreeSize(TNode* root)
{
	if (root == NULL)
	{
		return;
	}

	count++;
	TreeSize(root->_left);
	TreeSize(root->_right);
	return count;
}

这种方法需要定义一个全局变量,怎么可以不用全局变量
递归的原理就是分治法
在这里插入图片描述
比如校长想知道全校有多少学生,会叫来院长AB,院长AB又会让辅导员去统计,辅导员让班长去统计,然后班长统计完返回给辅导员,辅导员统计几个班长的总数返回给院长,院长统计完两个辅导员的总数返回给校长。整个过程就是将大问题化为越来越小的问题,直到可以得出答案,然后返回小问题的结果

int TreeSize(TNode* root)
{
	if (root == NULL)
	{
		return 0;
	}

	return TreeSize(root->_left)
		+ TreeSize(root->_right)
		+ 1;
}

这个画图之后和后序遍历的过程相似,空就返回0,后序左右子树遍历完再加上自身的1然后返回给上一层
在这里插入图片描述

4. 高度的计算

高度就是求二叉树中路径最长的一条有多少结点。类似上面那个图,校长想知道哪个哪个院人数最多,不断向下分解为求哪个班人数最多。辅导员比较左右两个班哪个人数最多,返回最多的。然后院长比较哪个辅导员最多,返回最多的。在二叉树分解到叶子结点,就是要比较左右节点,如果有就返回1,不断累加

int TreeHigh(TNode* root)
{
	if (root == NULL)
	{
		return 0;
	}

	/*return  TreeHigh(root->_left) > TreeHigh(root->_right)
		? TreeHigh(root->_left) + 1
		: TreeHigh(root->_right)+ 1;*/
	int left = TreeHigh(root->_left);
	int right = TreeHigh(root->_right);
	return left > right ? left + 1 : right + 1;

}

在这里插入图片描述

虽然上面两个方法都可以求得高度,但效率有很大的区别。屏蔽了的代码销毁慢很多,这种返回不会记录数量,每一次比较谁大都需要重新递归,越往节点上层对大的一方加1并不知道具体数量,所以需要将大的一方所有过程重新递归一遍,越往根节点走消耗等比增长。相当于校长想知道哪个班人数最多,班长返回给辅导员,辅导员往院长汇报没记录数量,又得重新走一遍最多的班询问数量,返回给院长,院长统计汇报时又得问辅导员数量,辅导员又得比较两个班长,将刚才的过程重复一遍,越往上,会将下一层整个过程重复,消耗越来越大

在这里插入图片描述

5. 第k层结点个数

求第k层的结点个数,求第3层的话,对于根节点来说就是求3层,对于根节点下一层来说就是求他的第2层,当k变为1的时候,意味着就是要求的这一层。放到学校体系里,想知道有多少个辅导员,就需要院长这一层来统计,所以想知道第3层有多少结点,就需要第2层来统计,往上汇总,所以有两个返回条件

1.结点为NULL,返回0
2.结点不为空,k是1

int TreeK(TNode* root, int k)
{
	assert(k > 0);

	if (root == NULL)
	{
		return 0;
	}

	if (k == 1)
	{
		return 1;
	}

	return TreeK(root->_left, k - 1) + TreeK(root->_right, k - 1);
}

当判断k是不是1的时候,节点为空在上面已经判断了。k代为3,画一下这个递归过程
在这里插入图片描述

6. 查找值

二叉树查找值返回的是节点的地址,需要注意递归中返回的不是最外层,而是返回给上一层调用自己的一层,需要保存返回值再往上一层层传递,上一层不断保存下一层传递上来的返回值

TNode* FindNode(TNode* root, TDataType x)
{
	if (root == NULL)
		return NULL;

	if (root->_data == x)
	{
		return root;
	}
	//保存返回的结果
	TNode* le = FindNode(root->_left, x);
	if (le)
	{
		return le;
	}
	TNode* rig = FindNode(root->_right, x);
	if (rig)
	{
		return rig;
	}
	//都没找到返回空
	//return FindNode(root->_right, x);
	return NULL;
}

在这里插入图片描述

7. 判断完全二叉树

完全二叉树的判断和层序遍历有关系。同样用一个队列,这时将空节点也压入,当层序遍历到空结点的时候,证明到了完全二叉树的结尾处,这时,如果出队列时有非空值就不是完全二叉树

bool isCompeteTree(TNode* root)
{
	Queue que;
	Init(&que);

	if (root != NULL)
	{
		Push(&que, root);
	}

	while (!Empty(&que))
	{
		TNode* top = Front(&que);
		//遇到空开始判断,如果有非空不是完全二叉树
		Pop(&que);
		if (top == NULL)
		{
			break;
		}
		//不是空就压入左右子树,需要压入空
		Push(&que, top->_left);
		Push(&que, top->_right);
	}

	//检查有没有非空
	while (!Empty(&que))
	{
		TNode* top = Front(&que);
		Pop(&que);

		if (top != NULL)
		{
			Destory(&que);
			return false;
		}

	}

	return true;
}

在这里插入图片描述

8. 销毁

二叉树的销毁需要遵循后续遍历的原则,左右子树都销毁了才能销毁根节点

void Destory(TNode* root)
{
	if (root == NULL)
	{
		return;
	}

	Destory(root->_left);
	Destory(root->_right);
	free(root);
}

在这里插入图片描述
在这里插入图片描述

9. OJ题

9.1 比较

相同的树: https://leetcode.cn/problems/same-tree/description/
在这里插入图片描述

思路
和遍历二叉树一样,在遍历的过程中比较,这里使用先序遍历,如果根不相等,就没必要往下继续比较了,最后返回这两个数与的结果,如果两个数都是空,就返回true,有一个不是空,就返回false,接着判断值

bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    
    if(p == NULL && q == NULL)
        return true;

    if(p == NULL || q== NULL)
        return false;
    if(p->val != q->val)
    {
        return false;
    }

    return  isSameTree(p->left, q->left) 
    &&  isSameTree(p->right,q->right);
}

9.2 单值二叉树

单值二叉树: https://leetcode.cn/problems/univalued-binary-tree/
在这里插入图片描述
思路
可以利用传递性,a=b=c,那么a=c。先比较根和左右节点是否相等,然后把子树当做根,比较它自己的左右子树,一直这样下去。注意判断反条件,因为相等得不出任何返回,还需要继续向下比较。最后递归返回两个子树向上传递的返回结果

bool isUnivalTree(struct TreeNode* root) {
    
    if (root == NULL)
    {
        return true;
    }

    //比较子树的值和根节点的值,确保不是空
    if (root->left && root->left->val != root->val)
    {
        return false;
    }
    if (root->right && root->right->val != root->val)
    {
        return false;
    }

    return isUnivalTree(root->left) && isUnivalTree(root->right);
}

在这里插入图片描述

9.3 镜像二叉树

镜像二叉树: https://leetcode.cn/problems/symmetric-tree/
在这里插入图片描述

思路
根结点不用比,因为没有对称节点。对称就是要根节点的左右节点互相相比。所以封装一个函数,分别传入根节点的左右结点,左子树的左节点和右子树的右结点,右结点和左节点相比

 bool isSymmetriclr(struct TreeNode* left, struct TreeNode* right)
 {
     //都为空
     if(left == NULL && right == NULL)
     {
         return true;
     }
    //有一个为空
     if(left == NULL || right == NULL)
     {
         return false;
     }
    //值不相等
     if(left->val != right->val)
     {
         return false;
     }
    //返回传递结果
     return isSymmetriclr(left->left, right->right)
         &&  isSymmetriclr(left->right,right->left);

 }
bool isSymmetric(struct TreeNode* root) {
   return isSymmetriclr(root->left, root->right);
}

在这里插入图片描述

9.4 二叉树遍历

二叉树遍历:https://leetcode.cn/problems/binary-tree-preorder-traversal/description/
在这里插入图片描述
思路
这个题目函数中给出了一个指针用来返回数组的大小,意思是将遍历结果放入数组之中。所以需要申请一个数组,而数组的大小可以先求一下二叉树的数量来确定,当前序遍历的时候,给定函数中不能递归,每次都会重新开辟空间。所以封装一个函数,传入这个数组指针,再记录一个下标,每放一下增加下标位置。要想让递归过程下标每放一次数据加一下,就得使用全局变量,但全局变量容易产生问题。所以传入一个指针,用下标访问每次改变下标值

int treesize(struct TreeNode* root) {
    if (root == NULL) {
        return 0;
    }

    return treesize(root->left) + treesize(root->right) + 1;
}

void preprint(struct TreeNode* root, int* ary, int* pi)
{
    if(root == NULL)
    {
        return;
    }

    ary[(*pi)++] = root->val;
    preprint(root->left,ary,pi);
    preprint(root->right,ary,pi);
}

int* preorderTraversal(struct TreeNode* root, int* returnSize) {

    //计算空间大小
    *returnSize = treesize(root);
    int* ary = (int*)malloc(sizeof(int) * (*returnSize));
    
   int i = 0;
   //传入数组和下标地址
    preprint(root, ary, &i);
    return ary;
}

在这里插入图片描述

9.5 子树

另一棵树的子树:https://leetcode.cn/problems/subtree-of-another-tree/description/
在这里插入图片描述

思路
可以利用前面的判断两个数相同的代码,在这里如果遇到空就返回false。先比较根结点,然后比较左右子树,递归这个过程。注意:只要有一次比较相同那么整个结果就是相同的

bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    
    if(p == NULL && q == NULL)
        return true;

    if(p == NULL || q== NULL)
        return false;
    if(p->val != q->val)
    {
        return false;
    }

    return  isSameTree(p->left, q->left) 
    &&  isSameTree(p->right,q->right);
}

bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){

    if (root == NULL)
    {
        return false;
    }
    if(isSameTree(root, subRoot))
    {
        return true;
    }
    return isSubtree(root->left, subRoot)
      || isSubtree(root->right,subRoot);


}

在这里插入图片描述

9.6 二叉树遍历

二叉树遍历: https://www.nowcoder.com/practice/4b91205483694f449f94c179883c1fef?tpId=60&&tqId=29483&rp=1&ru=/activity/oj&qru=/ta/tsing-kaoyan/question-ranking
在这里插入图片描述

先手动构建一下这个过程,给定字符串是先序的结果,所以第1个是根节点,第二个是左子树,根据这个顺序画出二叉树
在这里插入图片描述

思路
题目没给出,所以要自己写一个二叉树的结构体。根绝输入的字符串判断,如果是#,说明是空节点,就直接返回。如果不是,就创建该节点,然后链接递归自己的左右结点

#include <stdio.h>
typedef int TDataType;
typedef struct BinaryTreeNode {
    TDataType _data;
    struct BinaryTreeNode* _left;
    struct BinaryTreeNode* _right;
} TNode;
TNode* BuyNode(TDataType data) {
    TNode* newnode = (TNode*)malloc(sizeof(TNode));
    if (newnode == NULL) {
        perror("mallco");
        return NULL;
    }

    //初始化数据
    newnode->_data = data;
    newnode->_left = NULL;
    newnode->_right = NULL;
    return newnode;
}

TNode* CreaTree(char* ary, int* p) {
    if (ary[*p] == '#') {
        (*p)++;
        return NULL;
    }

    TNode* root = BuyNode(ary[*p]);
    (*p)++;

    root->_left = CreaTree(ary, p);
    root->_right = CreaTree(ary, p);
    return root;
}
void PrePrint(TNode* root) {
    if (root == NULL) {
        return;
    }

    PrePrint(root->_left);
    printf("%c ", root->_data);
    PrePrint(root->_right);

}
int main() {
    char ary[100];
    scanf("%s", ary);

    int i = 0;
    TNode* root = CreaTree(ary, &i);
    PrePrint(root);
    return 0;
}

在这里插入图片描述

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

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

相关文章

服装行业ERP系统解决方案

我国的服装企业大多属于劳动密集型&#xff0c;主要有三种类型&#xff1a;自有品牌服装生产销售企业、接订单生产型企业及处于产业链下游的零售分销企业。在经营过程中&#xff0c;服装行业面临诸多挑战&#xff0c;如流行周期短、季节性强&#xff0c;市场变化快&#xff1b;…

【HarmonyOS 4.0 应用开发实战】TypeScript入门之元组详讲

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

小程序软件测试应该怎么做?有什么作用?

近年来&#xff0c;随着移动互联网的快速发展&#xff0c;小程序软件的使用越来越广泛。无论是企业推广还是个人创作&#xff0c;小程序软件都具备了很大的潜力和市场空间。然而&#xff0c;在发布之前&#xff0c;进行充分的测试是至关重要的&#xff0c;以确保用户体验的顺畅…

【算法】Partitioning the Array(数论)

题目 Allen has an array a1,a2,…,an. For every positive integer k that is a divisor of n, Allen does the following: He partitions the array into n/k disjoint subarrays of length k. In other words, he partitions the array into the following subarrays: [a1,…

非接触式激光测厚仪 单点/三点/多点在线测厚设备

关键字: 非接触式激光测厚仪, 板材厚度检测,激光测厚仪,单点测厚仪,三点测厚仪,多点测厚仪,扫描式激光测厚仪, 厚度是各类板材品质必检的尺寸之一 在实际测量中&#xff0c;板材厚度的测量&#xff0c;尤其是宽板中间位置的厚度尺寸测量&#xff0c;是一项较为困难的工作。为此…

【笔记】CSDN文本编辑操作(持续更新中......)

文章目录 1、修改字体颜色和字号2、首行悬进两个字符3、图片居中4、字体、文字颜色、居中5、高亮6、重点标注7、加粗 1、修改字体颜色和字号 <html><head><meta http-equiv"Content" content"text/html;charsetutf-8" /><title>修…

C++大学教程(第九版)7.30 打印array对象 7.31 逆序打印字符串(递归练习题)

文章目录 题目代码运行截图题目代码运行截图 题目 (打印array对象)编写一个递归函数printArray它以一个array对象一个开始下标和一个结束下标作为实参&#xff0c;不返回任何值并打印这个array对象。当开始下标和结束下标相等时&#xff0c;这个函数应该停止处理并返回。 代码…

占预算仅20%,却是影响算力性能的关键

作者&#xff1a;林小引 戴尔科技解决方案架构师 ChatGPT迅速火爆全球后&#xff0c;人工智能进入了“暴力美学”时代。所谓暴力美学就是我们把模型的架构做到了超大规模&#xff0c;把算力的需求做到超大规模&#xff0c;训练的数据做到超大规模。 如果说算力是人工智能发展的…

STL标准模版在VS2019中的使用方法

STL标准模版在VS2019中的使用方法 1.STL在VS2019中的位置 1.STL在VS2019中的位置 1.1找到程序安装位置&#xff1a; D:\visual_studio\IDE\VC\Tools\MSVC\14.29.30133\include

重发布

一&#xff1a;作用 在两种路由协议之间&#xff0c;或者一个协议的不同进程之间&#xff0c;借助ASBR &#xff08;同时工作在两种协议或 者协 议的不同进程中&#xff09;学习到两个网络的路由信息&#xff0c;并且通过重发布进行路由共享&#xff0c;最终实现全网可 达。…

车载电子电器架构 —— IP地址获取策略

车载电子电器架构 —— IP地址获取策略 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自…

[网络安全 渗透实验 01]基于MSF框架渗透攻击Win7主机系统的设计与实现

基于MSF框架渗透攻击Win7主机系统的设计与实现 文章目录 基于MSF框架渗透攻击Win7主机系统的设计与实现[Warning] 写在前面1. 实验要求2. 实验环境搭建2.1 攻击机&#xff08;Linux kali&#xff09;的下载与安装2.2 靶机&#xff08;Windows 7 Enterprise with Service Pack 1…

旷视low-level系列(二):Practical Deep Raw Image Denoising on Mobile Devices

论文&#xff1a;ECCV 2020 代码&#xff1a;https://github.com/MegEngine/PMRID 文章目录 1. Motivation2. Contribution3. Methods3.1 噪声建模&参数估计3.2 k-Sigma变换3.3 移动端友好的网络结构 4. Experiments5. Comments 1. Motivation 业内周知&#xff0c;基于深…

Kotlin快速入门系列4

Kotlin的类与对象 类的定义 Kotlin使用关键字class来声明类。后面紧跟类名字&#xff1a; class LearnKotlin { //类名&#xff1a;LearnKotlin//... } Kotlin的类可以包含&#xff1a;构造函数和初始化代码块、函数、属性、内部类、对象声明。当然&#xff0c;也可以定义一…

vue实现查询搜索框下拉字典

字典表 前端页面显示 依据这个字典表实现动态查询 初始化数组 首先先在全局变量里定义一个数据存放查询出来的数据 data() {return {dicts: []};},生命周期 查询的时候是声明周期开始的时候&#xff0c;原本增删改查页面在生命周期开始的时候就查询了页面的数据获得了列表值…

IEEE| IceNet《IceNet for Interactive Contrast Enhancement》论文超详细解读(翻译+精读)

学习资料&#xff1a; 论文题目&#xff1a;《IceNet for Interactive Contrast Enhancement》&#xff08;用于交互式对比度增强的IceNet&#xff09;原文地址&#xff1a;export.arxiv.org/pdf/2109.05838v2.pdf 目录 ABSTRACT—摘要 翻译 精读 I. INTRODUCTION—简介 翻…

Thinkphp5.0.23远程代码执行漏洞复现

★★免责声明★★ 文章中涉及的程序(方法)可能带有攻击性&#xff0c;仅供安全研究与学习之用&#xff0c;读者将信息做其他用途&#xff0c;由Ta承担全部法律及连带责任&#xff0c;文章作者不承担任何法律及连带责任。 1、漏洞介绍 使用Thinkphp5.x远程代码执行漏洞&#xf…

26元/月起!腾讯云自动搭建4核16G雾锁王国服务器

腾讯云无需任何配置自动搭建雾锁王国4-8人联机服务器&#xff0c;游戏24小时在线&#xff0c;4核16G服务器低至26元/月起&#xff0c;一键搭建自己的雾锁王国联机服务器&#xff01; 第一步&#xff1a;购买服务器 1、通过【腾讯云游戏服专属优惠】页面&#xff0c;选择“雾锁…

关于v8垃圾回收机制以及与其相关联的知识点--还没整理版本

对于值类型b来说&#xff0c;就直接释放了其占用的内存&#xff0c;对于引用类型obj来说&#xff0c;销毁的只是变量obj对堆内存地址 1001 的引用&#xff0c;obj的值 { c: 3 } 依然存在于堆内存中。那么堆内存中的变量如何进行回收呢&#xff1f; V8的垃圾回收策略主要是基于…

YOLOv5改进系列(29)——添加DilateFormer(MSDA)注意力机制(中科院一区顶刊|即插即用的多尺度全局注意力机制)

【YOLOv5改进系列】前期回顾&#xff1a; YOLOv5改进系列&#xff08;0&#xff09;——重要性能指标与训练结果评价及分析 YOLOv5改进系列&#xff08;1&#xff09;——添加SE注意力机制 YOLOv5改进系列&#xff08;2&#xff09;——添加CBAM注意力机制 YOLOv5改进系列&…