数据结构 | 二叉树(基本概念、性质、遍历、C代码实现)

1.树的基本概念

树是一种 非线性 的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。
把它叫做树是因 为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。
有一个特殊的结点,称为根结点,根结点没有前驱结点 除根结点外,其余结点被分成M(M>0)个互不相交的集合T1、T2、……、Tm
其中每一个集合Ti(1<= i <= m)又是一棵结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继
因此, 树是递归定义 的。
结点的度:一个结点含有的子树的个数称为该结点的度;
叶结点:度为0的结点称为叶结点;
分支结点:度不为0的结点; 
父结点:若一个结点含有子结点,则这个结点称为其子结点的父结点;
子结点:一个结点含有的子树的根结点称为该结点的子结点;
兄弟结点:具有相同父结点的结点互称为兄弟结点;
树的度:一棵树中,最大的结点的度称为树的度; 
结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推;
树的高度或深度:树中结点的最大层次; 

2.二叉树的基本概念

一棵二叉树是结点的一个有限集合,该集合:
1. 或者为空
2. 由一个根结点加上两棵别称为左子树和右子树的二叉树组成
注意:二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树

2.1特殊的二叉树

满二叉树

一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。

完全二叉树

特征:前n-1层都是满的,最后一层可以不满,但最后一层从左到右必须是连续的。
ps: 满二叉树是一种特殊的完全二叉树。

3.二叉树的性质

1. 若规定根结点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1)个结点.
2. 若规定根结点的层数为1,则深度为h的二叉树的最大结点数是2^h-1
3. 对任何一棵二叉树, 如果度为0其叶结点个数为 n0, 度为2的分支结点个数为 n2,则有 n0=n2 +1
4. 若规定根结点的层数为1,具有n个结点的满二叉树的深度h=log2(n+1)
5. 对于完全二叉树:
双亲序号:(i-1)/2  (i为子节点序号)
左孩子序号:2i+1  (i为双亲结点序号)
右孩子序号:2i+2 (i为双亲结点序号)
练习:一个具有767个结点的完全二叉树,其叶子结点个数为()
A 383
B 384
C 385
D 386
答案:B
详解:设有度为2节点n2个, 度为1节点n1个,度为0节点n0个,
767=n2+n1+n0
n2=n0-1
由上面两式可得:
767=n1+2n0-1
768=n1+2n0
由于2n0必为偶数,768为偶数,可得:n1为偶数
且完全二叉树中n1只能是1或0
因此n1=0
768=2n0
n0=384

4 .二叉树的存储结构

二叉树一般可以使用两种结构存储,一种顺序结构,一种链式结构。
1. 顺序存储
顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空 间的浪费。而现实中使用中只有堆才会使用数组来存储。二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。
2.链式存储
二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是
链表中每个结点由三个域组成,数据域左右指针域,左右指针分别用来给出该结点左孩子和右孩子所
在的链结点的存储地址 。链式结构又分为二叉链和三叉链。本文主要针对二叉链。

5.二叉树的遍历

5.1 前序、中序以及后序遍历

1. 前序遍历——根节点 左子树 右子树
2. 中序遍历——左子树  根节点 右子树
3. 后序遍历——左子树 右子树  根节点

5.2 层序遍历

层序遍历:一层一层地往下遍历

6.二叉树代码实现

思路

前序/中序/后序遍历

递归思想:将当前的大问题拆解成小问题

以前序遍历为例:

当前问题——打印根,打印左子树,打印右子树

子问题——如图

递归返回条件——root==NULL

前序遍历代码

//前序遍历 根节点 左节点 右节点
void BinaryTreePrevOrder(BTNode* root) {
	if (root == NULL) {
		printf("N ");
		return;
	}

	printf("%d ", root->data);
	BinaryTreePrevOrder(root->left);
	BinaryTreePrevOrder(root->right);
}

中序遍历代码

void BinaryTreeInOrder(BTNode* root) {
	if (root == NULL) {
		printf("N ");
		return;
	}
	BinaryTreeInOrder(root->left);
	printf("%d ", root->data);
	BinaryTreeInOrder(root->right);
}

后序遍历代码

void BinaryTreePostOrder(BTNode* root) {
	if (root == NULL) {
		printf("N ");
		return;
	}
	BinaryTreePostOrder(root->left);
	BinaryTreePostOrder(root->right);
	printf("%d ", root->data);
}

节点个数/叶子节点个数/树高/第k层叶子数

1.节点个数

递归思想:

情况1:空,0个

情况2:不为空,左子树+右子树+1

2.叶子节点个数

情况1:空,返回0

情况2:只有一个结点,返回1

情况3:左子树+右子树

3.树的高度

情况1:空,返回0

情况2:左子树和右子树高度中大的值+1

4.第k层叶子数

情况1:空,返回0

情况2:非空,k==1,返回1

情况3:非空,k>1,左子树第k-1层+右子树第k-1层

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

}


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


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;
}

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

查找值为x的节点

递归思想

情况1:空,返回NULL

情况2:不为空,根值为x,返回根节点

情况3:不为空,根值不为x,查找左子树,有则返回

             左子树中无,查找右子树,有则返回

             右子树中也无,返回空

BTNode* BinaryTreeFind(BTNode* root, BTDataType x) {
	BTNode* ret = NULL;
	if (root == NULL) {
		return NULL;
	}
	if (root->data == x) {
		ret = root;
		return ret;
	}
	if (BinaryTreeFind(root->left, x) != NULL) {
		ret = BinaryTreeFind(root->left, x);
	}
	if (BinaryTreeFind(root->right, x) != NULL) {
		ret = BinaryTreeFind(root->right, x);
	}
}

层序遍历/完全二叉树

层序遍历

1.根进队列

2.节点出队列时,该节点的子节点(非空)进队列

3.当队列为空时,循环结束

完全二叉树

1.进行层序遍历,空也进队列

2.遇到第一个空节点,开始判断,后面全空就是完全二叉树,后面有非空就不是完全二叉树

void BinaryTreeLevelOrder(BTNode* root) {
	if (!root) {
		return;
	}
	Queue q;
	QueueInit(&q);
	QueuePush(&q, root);
	
	while (QueueSize(&q) > 0) {
		BTNode* head = QueueFront(&q);
		if (head->left) {
			QueuePush(&q, head->left);
		}
		if (head->right) {
			QueuePush(&q, head->right);
		}
		printf("%d", head->data);
		QueuePop(&q);
	}
	QueueDestroy(&q);
}


bool BinaryTreeComplete(BTNode* root) {
	if (!root) {
		return;
	}
	Queue q;
	QueueInit(&q);
	QueuePush(&q, root);

	while (QueueSize(&q) > 0) {
		BTNode* head = QueueFront(&q);
		if (head == NULL) {
			break;
		}
			QueuePush(&q, head->left);
			QueuePush(&q, head->right);
		QueuePop(&q);
	}
	while(!QueueEmpty(&q)){
		BTNode* head = QueueFront(&q);
		if (head) {
			QueueDestroy(&q);
			return false;
		}
		QueuePop(&q);
	}
	QueueDestroy(&q);
	return true;
}

代码汇总

binarytree.h

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int BTDataType;

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

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate();
// 二叉树销毁
void BinaryTreeDestory(BTNode* root);
// 二叉树节点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root);
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);
// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTNode* root);

binarytree.c

#define _CRT_SECURE_NO_WARNINGS
#include "binarytree.h"
#include "queue.h"


BTNode* BuyNode(BTDataType x) {
	BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
	if (newnode == NULL) {
		perror("malloc fail!");
	}
	newnode->left = NULL;
	newnode->right = NULL;
	newnode->data = x;
	return newnode;
}

BTNode* BinaryTreeCreate() {
	BTNode* Node1 = BuyNode(1);
	BTNode* Node2 = BuyNode(2);
	BTNode* Node3 = BuyNode(3);
	BTNode* Node4 = BuyNode(4);
	BTNode* Node5 = BuyNode(5);
	BTNode* Node6 = BuyNode(6);
	BTNode* Node7 = BuyNode(7);
	
	Node1->left = Node2;
	Node1->right = Node3;
	Node2->left = Node4;
	Node2->right = Node5;
	Node3->left = Node6;
	//Node6->left = Node7;

	return Node1;//返回根节点
}
//前序遍历 根节点 左节点 右节点
void BinaryTreePrevOrder(BTNode* root) {
	if (root == NULL) {
		printf("N ");
		return;
	}

	printf("%d ", root->data);
	BinaryTreePrevOrder(root->left);
	BinaryTreePrevOrder(root->right);
}

void BinaryTreeInOrder(BTNode* root) {
	if (root == NULL) {
		printf("N ");
		return;
	}
	BinaryTreeInOrder(root->left);
	printf("%d ", root->data);
	BinaryTreeInOrder(root->right);
}

void BinaryTreePostOrder(BTNode* root) {
	if (root == NULL) {
		printf("N ");
		return;
	}
	BinaryTreePostOrder(root->left);
	BinaryTreePostOrder(root->right);
	printf("%d ", root->data);
}





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

}


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


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

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;
}

BTNode* BinaryTreeFind(BTNode* root, BTDataType x) {
	BTNode* ret = NULL;
	if (root == NULL) {
		return NULL;
	}
	if (root->data == x) {
		ret = root;
		return ret;
	}
	if (BinaryTreeFind(root->left, x) != NULL) {
		ret = BinaryTreeFind(root->left, x);
	}
	if (BinaryTreeFind(root->right, x) != NULL) {
		ret = BinaryTreeFind(root->right, x);
	}
}


void BinaryTreeLevelOrder(BTNode* root) {
	if (!root) {
		return;
	}
	Queue q;
	QueueInit(&q);
	QueuePush(&q, root);
	
	while (QueueSize(&q) > 0) {
		BTNode* head = QueueFront(&q);
		if (head->left) {
			QueuePush(&q, head->left);
		}
		if (head->right) {
			QueuePush(&q, head->right);
		}
		printf("%d", head->data);
		QueuePop(&q);
	}
	QueueDestroy(&q);
}


bool BinaryTreeComplete(BTNode* root) {
	if (!root) {
		return;
	}
	Queue q;
	QueueInit(&q);
	QueuePush(&q, root);

	while (QueueSize(&q) > 0) {
		BTNode* head = QueueFront(&q);
		if (head == NULL) {
			break;
		}
			QueuePush(&q, head->left);
			QueuePush(&q, head->right);
		QueuePop(&q);
	}
	while(!QueueEmpty(&q)){
		BTNode* head = QueueFront(&q);
		if (head) {
			QueueDestroy(&q);
			return false;
		}
		QueuePop(&q);
	}
	QueueDestroy(&q);
	return true;
}

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

	BinaryTreeDestory(root->left);
	BinaryTreeDestory(root->right);
	free(root);
}

在实现层序遍历时,会使用到队列。但由于C语言中没有现成的数据结构队列可以直接使用,需要自己实现。

queue.h

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef struct BinaryTreeNode* QDataType;

typedef struct QListNode{
	struct QListNode* next;
	QDataType data;
}QNode;

// 队列的结构 
typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;

// 初始化队列 
void QueueInit(Queue* q);
// 队尾入队列 
void QueuePush(Queue* q, QDataType data);
// 队头出队列 
void QueuePop(Queue* q);
// 获取队列头部元素 
QDataType QueueFront(Queue* q);
// 获取队列队尾元素 
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数 
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q);
// 销毁队列 
void QueueDestroy(Queue* q);

queue.c

#define _CRT_SECURE_NO_WARNINGS
#include "queue.h"
// 初始化队列 
void QueueInit(Queue* q) {
	assert(q);
	q->phead = q->ptail = NULL;
	q->size = 0;
}
// 队尾入队列 
void QueuePush(Queue* q, QDataType data) {
	assert(q);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL) {
		perror("malloc fail!");
		exit(1);
	}
	else {
		newnode->data = data;
		newnode->next = NULL;
		if (q->ptail == NULL) {
			q->phead = q->ptail = newnode;
			q->size++;
		}
		else {
			q->ptail->next =newnode;
			q->ptail = newnode;
			q->size++;
		}
	}
}
// 队头出队列 
void QueuePop(Queue* q) {
	assert(q);
	assert(q->size != 0);
	if (q->phead->next == NULL) {
		free(q->ptail);
		q->ptail = q->phead = NULL;
		q->size--;
	}
	else {
		QNode* next = q->phead->next;
		free(q->phead);
		q->phead = next;
		q->size--;
	}
}
// 获取队列头部元素 
QDataType QueueFront(Queue* q) {
	assert(q);
	assert(q->size > 0);
	return q->phead->data;
}
// 获取队列队尾元素 
QDataType QueueBack(Queue* q) {
	assert(q);
	assert(q->size > 0);
	return q->ptail->data;
}
// 获取队列中有效元素个数 
int QueueSize(Queue* q) {
	assert(q);
	return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q) {
	assert(q);
	return !QueueSize(q);
}
// 销毁队列 
void QueueDestroy(Queue* q) {
	assert(q);
	while (q->size) {
		QueuePop(q);
	}
	q->phead = NULL;
	q->ptail = NULL;
}

7.堆及堆排序及TopK问题

详见我的另一篇文章~(TopK问题待更)

数据结构 | 详解二叉树——堆与堆排序

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

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

相关文章

社交媒体数据恢复:云信Demo

一、准备工作 登录您的网易云信demo账号&#xff0c;确保您具有管理员权限。 确认您要恢复的数据类型&#xff0c;例如聊天记录、文件传输记录等。 确保您熟悉网易云信demo的后台管理界面和功能。 二、数据备份 在进行数据恢复之前&#xff0c;请先备份您现有的数据&#…

python移动文件

测试1(直接把B文件夹移动到了A里&#xff0c;成为了A的子文件夹) import os import shutil# 移动文件夹,B文件夹在当前目录没有了&#xff0c;跑到了A的子文件里 ## shutil.move(./example1/B/, ./example1/A/)测试2(B文件不动&#xff0c;将B文件里的所有的子文件夹移动到A内…

DuDuTalk:营业厅智能质检终端在通信运营商线下营业厅应用价值

在通信行业日益竞争的今天&#xff0c;线下营业厅网点是企业与客户互动的黄金触点&#xff0c;但由于缺乏有效管控和人员能力素质的层次不齐&#xff0c;如何提升线下营业厅的服务质量、提高运营效率&#xff0c;成为各大通信运营商亟待解决的问题。 在此背景下&#xff0c;我…

深入理解路由与视图函数绑定:从装饰器到Flask实战

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言&#xff1a;装饰器在路由绑定中的应用 二、Flask中的add_url_rule()方法 示例代码…

优思学院|作为质量工程师,需要考哪些证书?别浪费你的气力,一张就够!

质量工程师做什么呢&#xff1f;他们的主要任务就是确保产品和服务的质量&#xff0c;以满足客户需求并超越竞争对手。尽管市场上有各种各样的质量管理认证&#xff0c;但优思学院认为&#xff0c;专注于六西格玛的学习和认证就足够了。 为什么选择六西格玛&#xff1f; 第一…

Unity 实现让物体渲染在最前面

演示 实现方案 1.创建一个shader脚本 2.删掉原来的内容&#xff1a;我们自己写 附上完整的shader代码&#xff1a; Shader "Custom/ZTestAlways" {Properties {_Color ("Color Tint",Color) (1,1,1,1)_MainTex("Main Tex",2D) "white&q…

obsidian zotero 联动方案 配置记录 by ZotLit Zotero style

前言 Obsidian 和 zotero 都是非常好用的开源软件&#xff0c;两个软件能做到无缝联动也是很多人的想法&#xff0c;文献笔记可以丝滑的放进 obsidian 中&#xff0c;那多好&#xff0c;网上有很多教程&#xff0c;但能够一步到位讲清楚的很少。我也踩了很多坑才完成部署&…

网络四层、七层协议

一、OSI七层模型 物理层&#xff1a;建立、维护、断开物理连接。 数据链路层&#xff1a;逻辑连接、寻找硬件地址——地址解析协议&#xff1a;ARP、PARP 反向地址转换协议 网络层&#xff1a;寻找逻辑地址&#xff0c;实现不同网络之间的路径选择——ICMP(互联网控制信息协议…

【开源】渔具租赁系统 JAVA+Vue.js+SpringBoot+MySQL

目录 一、项目介绍 1.1渔具档案模块 1.2渔具租赁模块 1.3渔具归还模块 1.4在线留言模块 二、项目截图 三、核心代码 一、项目介绍 Vue.jsSpringBoot前后端分离新手入门项目《渔具租赁系统》&#xff0c;包括渔具档案模块、渔具租赁模块、渔具归还模块、在线留言模块和部…

西藏大学计科改考11408!西藏大学计算机考研考情分析!

西藏大学&#xff08;Tibet University&#xff09;&#xff0c;简称藏大&#xff0c;是西藏自治区所属的综合性大学&#xff0c;是列入教育部直属高校序列的教育部与西藏自治区人民政府合建高校&#xff0c;国家“211工程”重点建设大学&#xff0c;国家“双一流”世界一流学科…

小角楼是怎样成为清廷御酒的?

执笔 | 扬 灵 编辑 | 古利特 “酒史千年远&#xff0c;酒花百代香&#xff0c;天府多佳酿&#xff0c;美酒驻平昌。” 对四川省巴中市平昌县而言&#xff0c;白酒是经济发展的重要产业之一&#xff0c;好山好水出好酒&#xff0c;优良的地质、水源、气候、土壤等条件以及悠久…

设计模式22——备忘录模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用&#xff0c;主要是下面的UML图可以起到大作用&#xff0c;在你学习过一遍以后可能会遗忘&#xff0c;忘记了不要紧&#xff0c;只要看一眼UML图就能想起来了。同时也请大家多多指教。 备忘录模式&#xff08;Mement…

LeetCode739:每日温度

题目描述 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温度出现在几天后。如果气温在这之后都不会升高&#xff0c;请在该位置用 0 来代替。 解题思想 使用单…

17-java网络编程

目录 第17章 网络编程 17.1 软件结构 17.2 网络通信三要素 17.2.1 IP地址和域名 1、IP地址 2、域名 17.2.2 端口号 17.2.3 网络通信协议 17.3 TCP与UDP协议 17.3.1 UDP协议 17.3.2 TCP协议 1、三次握手 2、四次挥手 17.4 网络编程API 17.4.1 InetAddress类 17.4…

B端UI设计,演绎高情逸态之妙

B端UI设计&#xff0c;演绎高情逸态之妙

达梦数据库(五) -------- 达梦数据库+mybatisPlus+springboot

前言&#xff1a;安装完达梦数据库后&#xff0c;需要初始化实例&#xff0c;在初始化实例时&#xff0c;需要注意大小写敏感的设置。大小写敏感只能在初始化数据库的时候设置&#xff0c;默认为大小写敏感&#xff0c;一旦设置成功就无法修改&#xff0c;如果想要修改&#xf…

DBeaver连接Elasticsearch

一、下载DBeaver 二、连接&#xff1a; 1、一定要选择开源的 Open Distro Elasticsearch 2、填写地址&#xff1a; 3、选择“URL”&#xff0c;将https改为http 否则会报SSL错误 4、测试连接

如何免费查到企业的公开信息?

很多小伙伴在查询企业信息的时候&#xff0c;都想要一个综合的平台能够查到企业多维度的信息。 然而企业的信息虽然是公开的&#xff0c;但是信息都分布在不同的网站上&#xff0c;比如企业公示系统&#xff0c;裁判文书网&#xff0c;知识产权网等。 一个企业就要用到多个网…

php反序列化学习(2)

1、魔术方法触发规则&#xff1a; 魔术方法触发的前提是&#xff1a;魔法方法所在类&#xff08;或对象&#xff09;被调用 分析代码&#xff0c;_wakeup()的触发条件是进行反序列化&#xff0c;_tostrinng()触发的条件是把对象当成字符串调用&#xff0c;但是魔术方法触发的前…

yolov10训练

yolov10训练 1 yolov10 COCO训练1.1 环境配置1.2 模型训练 2 yolov10 训练自己的数据集2.1 使用源码训练2.1.1 数据集的准备2.1.2 yolov10的预训练权重2.1.3 模型训练2.1.3.1 YOLO2.1.3.2 YOLOv10 2.1.4 模型验证 3 参考链接 论文代码&#xff1a;https://github.com/THU-MIG/y…