二叉树的介绍及二叉树的链式结构的实现(C语言版)

前言

        二叉树是一种特殊的树,它最大的度为2,每个节点至多只有两个子树。它是一种基础的数据结构,后面很多重要的数据结构都是依靠它来进行实现的。了解并且掌握它是很重要的。

目录

1.二叉树的介绍

        1.1概念

        1.2现实中的二叉树

        1.3特殊的二叉树

        1.4二叉树的性

        1.5二叉树的存储结构 

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

        2.1创建一颗伪二叉树

        2.2二叉树的遍历

                2.2.1前序,中序和后序遍历

                2.2.2层序遍历 

        2.3二叉树的节点个数及高度等

        2.4二叉树的创建及销毁 

        2.5全部代码


 

1.二叉树的介绍

        1.1概念

        一颗二叉树是节点的一个有限集合,该集合:

        1.或者为空

        2.由根节点外加两颗别称为左子树和右子树的二叉树组成

        1.2现实中的二叉树

        1.3特殊的二叉树

        满二叉树:一个二叉树,如果每一层的节点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且节点的总数是二的K次方-1,则它就是满二叉树。

        完全二叉树 : 完全二叉树是一种效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有N个节点的二叉树,当且仅当每个节点都与深度为K的满二叉树中编号从1到N的节点一一对应时,称为完全二叉树。

        1.4二叉树的性

         1.若规定根节点的层数为1,则一颗非空二叉树的第i层最多有2的i-1次方个节点

         2.若规定根节点的层数为1,则深度为h的二叉树最大的节点数为2的h次方减1。

         3.对于任意一颗二叉树,如果度为零其叶子结点的个数为n0,度为2的分支节点个数为n2,则有n0 = n2 + 1;

        4.若规定根节点的层数为1,其n个节点的满二叉树的深度,h = log2(n+1).(log2(n + 1)是以2为底,n+1为对数);

        5.对于具有n个节点的完全二叉树,如果按照从上至下,从左至右的数组顺序对所有的节点从0开始编号,则对于序号为i的节点有:

        1.若i大于0,i位置双亲节点的序号:(i - 1)/2; i = 0,i为根节点编号,无双亲节点

        2.若2i+1<n,左孩子的序号:2i+1;2i+1>=n,则无左孩子。

        3.若2i+2<n,右孩子序号:2i+2,2i+2>=n,则无右孩子。

        1.5二叉树的存储结构 

        二叉树一般有两种结构的存储方式,一种是顺序结构,一种是链式结构。

        1.顺序存储

        顺序存储使用的数组,一般数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费,而现实中只有堆 才使用数组来存储。二叉树的顺序存储在物理上是数组,在逻辑上是一颗二叉树。

         2.链式存储

        二叉树的链式存储结构是指,用链表来表示一颗二叉树,即用链表来指示元素之间的逻辑关系。通常的方法是每个节点由左,右指针域和数据域组成。左,右指针分别用来给出该节点左孩子和右孩子所在节点的地址。链式存储结构又分为二叉链和三叉链。现在我们使用的是二叉链。

         

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

        2.1创建一颗伪二叉树

        这里需要快速创建一颗二叉树,为了降低理解的难度,先创建一颗伪二叉树来进行学习,便于理解。

        //BTree.h

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef char BTDataType;
typedef struct BTreeNode
{BTDataType _data;struct BTreeNode* _left;struct BTreeNode* _right;
}BTreeNode;
BTreeNode* BuyBTreeNode(BTreeNode* node, BTDataType c);//申请一棵树的节点BTreeNode* CreatBinaryTree(BTreeNode* root);//创建一棵树

        //BTree.c

BTreeNode* BuyBTreeNode(BTreeNode* node,BTDataType c)
{BTreeNode*cur = (BTreeNode*)malloc(sizeof(BTreeNode));cur->_data = c;cur->_left = cur->_right = NULL;
}
BTreeNode* CreatBinaryTree(BTreeNode* root)//创建一棵树
{root = BuyBTreeNode(root, 'A');BTreeNode* B = BuyBTreeNode(root, 'B');BTreeNode* C = BuyBTreeNode(root, 'C');BTreeNode* D = BuyBTreeNode(root, 'D');BTreeNode* E = BuyBTreeNode(root, 'E');BTreeNode* F = BuyBTreeNode(root, 'F');root->_left = B;root->_right = C;B->_left = D;C->_left = E;C->_right = F;return root;
}

        2.2二叉树的遍历

                2.2.1前序,中序和后序遍历

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

        按照规则二叉树的遍历有:前序,中序和后序的递归结构遍历:

        1.前序遍历(Preorder Traversal ),亦称为先序遍历,访问根节点的操作发生在访问左右子树之前。

        2.中序遍历(Inorder Traversal)--访问根节点的操作发生在访问左右子树之间。

        3.后序遍历(Post Traversal)--访问根节点的操作发生在左右子树之后。

        由于被访问的节点必是某树的根,所以N(Node) ,L(Left subtree)和R(Right subtree)又可以解释为,根节点,根的左子树和根的右子树。NLR,LNR,LRN分别称为先根遍历,中根遍历和后根遍历。

        

        前序遍历的代码:

// 二叉树前序遍历
void PreOrder(BTreeNode* root)
{if (root == NULL){printf("NULL ");return;}printf("%c ",root->_data);PreOrder(root->_left);//左子树PreOrder(root->_right);//右子树
}

        前序遍历的递归图解: 

 

        中序遍历和后序遍历的代码: 

        

// 二叉树中序遍历
void InOrder(BTreeNode* root)
{if (root == NULL){printf("NULL ");return;}PreOrder(root->_left);//左子树printf("%c ", root->_data);//根PreOrder(root->_right);//右子树
}
// 二叉树后序遍历
void PostOrder(BTreeNode* root)
{if (root == NULL){printf("NULL ");return;}PreOrder(root->_left);//左子树PreOrder(root->_right);//右子树printf("%c ", root->_data);//根}

         中序和后序遍历的展开图解和前序遍历的类似,有兴趣的友友可以自己画画看。

                2.2.2层序遍历 

        二叉树的层序遍历是通过借助队列来实现的,将一颗树的根入队,出队时,如果根的左,右节点不为空就将根的左右节点依次入队,当队列为空时结束循环,这样就完成了二叉树的层序遍历。  

void LevelOrder(BTreeNode* root)//层序遍历
{//创建队列Queue q;QueueInit(&q);QueuePush(&q, root);while (!QueueEmpty(&q))//队列不为空,出队头的元素,同时取节点判断左右子树是否为空{BTreeNode* cur = QueueFront(&q);QueuePop(&q);printf("%c ", cur->_data);if (cur->_left)//左子树存在{QueuePush(&q, cur->_left);//将当前节点的左子树入队}if (cur->_right)//右子树存在{QueuePush(&q, cur->_right);//将当前节点的右子树入队}}
}

        2.3二叉树的节点个数及高度等

        递归求二叉树的高度是在当前节点求出左,右子树的高度,再将左,右子树中高度大的那个加一就是当前树的高度。

int BinarTreelen(BTreeNode* root)//求树的高度
{if (root == NULL)return 0;int leftsize = BinarTreelen(root->_left);int rightsize = BinarTreelen(root->_right);return leftsize > rightsize ? leftsize + 1 : rightsize + 1;//高度等于下一层左右节点高的那个加1
}

        二叉树叶子结点的个数,通过递归求解,首先叶子节点肯定满足左右子树都为空,所以如果左右子树都为空的话,就直接返回1,说明当前节点就是叶子节点,否则继续递归去找叶子节点。

int BinaryTreeLeafSize(BTreeNode* root)
{if (root == NULL)//节点为空直接返回return 0;if (root->_left == NULL && root->_right == NULL)//左右节点都为空return 1;//说明当前节点为叶子节点return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);//递归去求左右子树
}

        求二叉树的节点个数,如果当前节点不为空,就+1,然后递归求左,右子树中的节点数。如果当前节点为NULL则返回0.

// 二叉树节点个数
int BinaryTreeSize(BTreeNode* root)
{if (root == NULL)//当前节点为NULLreturn 0;return 1 + BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right);//前序遍历的方式求树的节点个数
}

         二叉树查找值为x的节点,通过前序遍历二叉树,如果二叉树当前节点的值等于x就返回当前节点。

BTreeNode* BinaryTreeFind(BTreeNode* root, BTDataType x)
{if (root == NULL)//如果节点为NULLreturn NULL;//返回NULLif (root->_data == x)return root;//找到值为x的节点,返回BTreeNode*cur = BinaryTreeFind(root->_left, x);if (cur)//找到了就返回节点的地址return cur;cur = BinaryTreeFind(root->_right, x);if (cur)//找到了就返回节点的地址return cur;return NULL;//如果这棵树没有找到就返回NULL
}

        求二叉树的第K层的节点个数,采用分治的思想:一颗树第K层的节点等于左子树K-1层的节点+右子树K-1层的节点。  结束条件是,如果当K等于1时,返回1,当当前节点为NULL时返回0。

// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTreeNode* root, int _k)
{if (root == NULL)return 0;if (_k == 1 && root)//如果K等于1直接返回return 1;return BinaryTreeLevelKSize(root->_left, _k - 1) + BinaryTreeLevelKSize(root->_right, _k - 1);//递归到左,右子树K-1层中去找节点数
}

        判断一颗二叉树是不是完全二叉树,借助 队列,采用层序遍历的方式,但是这里不判断当前树的左右子树是否为空,取队头的数据时,直接将该节点的左,右子树入队。当取到的队头的数据为空时,结束循环。如果是完全二叉树,那么剩余在队列中的所有的NULL应该是连续的。再将队列中所有的元素都出队,如果全部为空就满足完全二叉树,如果不是就不满足完全二叉树。 

bool BinaryTreeComplete(BTreeNode* root)//判断一棵树是不是完全二叉树
{if (root == NULL)return true;//创建队列Queue q;QueueInit(&q);QueuePush(&q, root);while (!QueueEmpty(&q))//队列不为空,出队头的元素,同时判断取出来的节点是否为空{BTreeNode* cur = QueueFront(&q);QueuePop(&q);if (cur == NULL)break;//当前节点为空直接结束循环QueuePush(&q, cur->_left);QueuePush(&q, cur->_right);}while (!QueueEmpty(&q)){//判断队列中剩下的元素是否有不为空的BTreeNode* cur = QueueFront(&q);QueuePop(&q);if (cur)return false;}//如果走到这里还没有返回说明是完全二叉树return true;
}

        2.4二叉树的创建及销毁 

         通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树。

        思路:通过递归去构建二叉树,因为给出的是前序遍历的数组,而数组中的#表示NULL,因此需要参数来记录数组的位置,也需要将字符数组传递给构建函数,如果遇到#就返回NULL,如果不是就申请空间初始化data域,并且将申请的空间进行返回,然后去递归构建左右子树。

#include <stdio.h>
#include<stdlib.h>typedef struct BTreeNode
{char _data;struct BTNode* _left;struct BTNode* _right;}BTreeNode;void InOrder(BTreeNode* root){if (root == NULL)return;//左子树InOrder(root->_left);//根printf("%c ", root->_data);//右子树InOrder(root->_right);
}BTreeNode* BinaryTreeCreate(char* a, int* pi)
{if (a[*pi] == '#'){++(*pi);return NULL;}BTreeNode* node = (BTreeNode*)malloc(sizeof(BTreeNode));//申请节点node->_data = a[*pi];(*pi)++;//递归构建左右子树node->_left = BinaryTreeCreate(a, pi);node->_right = BinaryTreeCreate(a, pi);return node;
}
int main() 
{char s[50] = { 0 };scanf("%s", s);int i = 0;//使用前序遍历构建树BTreeNode* root = BinaryTreeCreate(s, &i);//使用中序遍历打印树的节点的值InOrder(root);return 0;
}

        二叉树的销毁,如果采用前序遍历的方式进行销毁,就需要保存当前节点,所以建议采用后序遍历的方式进行销毁。 

// 二叉树销毁
void BinaryTreeDestory(BTreeNode* root)//这里为了保持接口的一致性采用一级指针
{if (root == NULL)return;BinaryTreeDestory(root->_left);BinaryTreeDestory(root->_right);free(root);
}

        2.5全部代码

        //BTree.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
typedef char BTDataType;
typedef struct BTreeNode
{BTDataType _data;struct BTreeNode* _left;struct BTreeNode* _right;
}BTreeNode;
BTreeNode* BuyBTreeNode(BTreeNode* node, BTDataType c);//申请一棵树的节点BTreeNode* CreatBinaryTree(BTreeNode* root);//创建一棵树// 二叉树前序遍历
void PreOrder(BTreeNode* root);
// 二叉树中序遍历
void InOrder(BTreeNode* root);
// 二叉树后序遍历
void PostOrder(BTreeNode* root);// 二叉树节点个数
int BinaryTreeSize(BTreeNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTreeNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTreeNode* root, int _k);int BinarTreelen(BTreeNode* root);//求树的高度
// 二叉树查找值为x的节点
BTreeNode* BinaryTreeFind(BTreeNode* root, BTDataType x);void LevelOrder(BTreeNode* root);//层序遍历// 二叉树销毁
void BinaryTreeDestory(BTreeNode* root);
bool BinaryTreeComplete(BTreeNode* root);//判断一棵树是不是完全二叉树

         //BTree.c

#include"BTree.h"
#include"Queue.h"
BTreeNode* BuyBTreeNode(BTreeNode* node,BTDataType c)
{BTreeNode*cur = (BTreeNode*)malloc(sizeof(BTreeNode));cur->_data = c;cur->_left = cur->_right = NULL;return cur;
}
BTreeNode* CreatBinaryTree(BTreeNode* root)//创建一棵树
{root = BuyBTreeNode(root, 'A');BTreeNode* B = BuyBTreeNode(root, 'B');BTreeNode* C = BuyBTreeNode(root, 'C');BTreeNode* D = BuyBTreeNode(root, 'D');BTreeNode* E = BuyBTreeNode(root, 'E');BTreeNode* F = BuyBTreeNode(root, 'F');root->_left = B;root->_right = C;B->_left = D;C->_left = E;C->_right = F;return root;
}
// 二叉树前序遍历
void PreOrder(BTreeNode* root){if (root == NULL){ return;}printf("%c ",root->_data);PreOrder(root->_left);//左子树PreOrder(root->_right);//右子树
}
// 二叉树中序遍历
void InOrder(BTreeNode* root)
{if (root == NULL){printf("NULL ");return;}PreOrder(root->_left);//左子树printf("%c ", root->_data);//根PreOrder(root->_right);//右子树
}
// 二叉树后序遍历
void PostOrder(BTreeNode* root)
{if (root == NULL){printf("NULL ");return;}PreOrder(root->_left);//左子树PreOrder(root->_right);//右子树printf("%c ", root->_data);//根}// 二叉树节点个数
int BinaryTreeSize(BTreeNode* root)
{if (root == NULL)//当前节点为NULLreturn 0;return 1 + BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right);//前序遍历的方式求树的节点个数
}
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTreeNode* root)
{if (root == NULL)//节点为空直接返回return 0;if (root->_left == NULL && root->_right == NULL)//左右节点都为空return 1;//说明当前节点为叶子节点return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);//递归去求左右子树
}
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTreeNode* root, int _k)
{if (root == NULL)return 0;if (_k == 1 && root)//如果K等于1直接返回return 1;return BinaryTreeLevelKSize(root->_left, _k - 1) + BinaryTreeLevelKSize(root->_right, _k - 1);//递归到左,右子树K-1层中去找节点数
}
int BinarTreelen(BTreeNode* root)//求树的高度
{if (root == NULL)return 0;int leftsize = BinarTreelen(root->_left);int rightsize = BinarTreelen(root->_right);return leftsize > rightsize ? leftsize + 1 : rightsize + 1;//高度等于下一层左右节点高的那个加1
}
// 二叉树查找值为x的节点BTreeNode* BinaryTreeFind(BTreeNode* root, BTDataType x)
{if (root == NULL)//如果节点为NULLreturn NULL;//返回NULLif (root->_data == x)return root;//找到值为x的节点,返回BTreeNode*cur = BinaryTreeFind(root->_left, x);if (cur)//找到了就返回节点的地址return cur;cur = BinaryTreeFind(root->_right, x);if (cur)//找到了就返回节点的地址return cur;return NULL;//如果这棵树没有找到就返回NULL
}void LevelOrder(BTreeNode* root)//层序遍历
{//创建队列Queue q;QueueInit(&q);QueuePush(&q, root);while (!QueueEmpty(&q))//队列不为空,出队头的元素,同时取节点判断左右子树是否为空{BTreeNode* cur = QueueFront(&q);QueuePop(&q);printf("%c ", cur->_data);if (cur->_left)//左子树存在{QueuePush(&q, cur->_left);}if (cur->_right)//右子树存在{QueuePush(&q, cur->_right);}}
}// 二叉树销毁
void BinaryTreeDestory(BTreeNode* root)//这里为了保持接口的一致性采用一级指针
{if (root == NULL)return;BinaryTreeDestory(root->_left);BinaryTreeDestory(root->_right);free(root);
}
bool BinaryTreeComplete(BTreeNode* root)//判断一棵树是不是完全二叉树
{if (root == NULL)return true;//创建队列Queue q;QueueInit(&q);QueuePush(&q, root);while (!QueueEmpty(&q))//队列不为空,出队头的元素,同时判断取出来的节点是否为空{BTreeNode* cur = QueueFront(&q);QueuePop(&q);if (cur == NULL)break;//当前节点为空直接结束循环QueuePush(&q, cur->_left);QueuePush(&q, cur->_right);}while (!QueueEmpty(&q)){//判断队列中剩下的元素是否有不为空的BTreeNode* cur = QueueFront(&q);QueuePop(&q);if (cur)return false;}//如果走到这里还没有返回说明是完全二叉树return true;
}#include <stdio.h>
#include<stdlib.h>typedef struct BTreeNode
{char _data;struct BTNode* _left;struct BTNode* _right;}BTreeNode;void InOrder(BTreeNode* root){if (root == NULL)return;//左子树InOrder(root->_left);//根printf("%c ", root->_data);//右子树InOrder(root->_right);
}BTreeNode* BinaryTreeCreate(char* a, int* pi)
{if (a[*pi] == '#'){++(*pi);return NULL;}BTreeNode* node = (BTreeNode*)malloc(sizeof(BTreeNode));//申请节点node->_data = a[*pi];(*pi)++;//递归构建左右子树node->_left = BinaryTreeCreate(a, pi);node->_right = BinaryTreeCreate(a, pi);return node;
}

//Queue.h

#pragma once
#include<stdlib.h>
#include<assert.h>
#include<stdio.h>
#include<stdbool.h>
typedef struct BTreeNode BTreeNode;
typedef  BTreeNode* QDataType;//树节点的声明typedef struct QueueNode
{struct QueueNode* _next;QDataType _data;
}QueueNode;
typedef struct  Queue//队列的结构
{QueueNode* _head;//头指针QueueNode* _tail;//尾指针
}Queue;void QueueInit(Queue* qu);//初始化栈void QueueDestory(Queue* qu);//摧毁栈void QueuePush(Queue* qu,QDataType data);//入队void QueuePop(Queue* qu);//出队QDataType QueueFront(Queue* qu);//返回队头元素
QDataType QueueBack(Queue* qu);//返回队尾元素size_t QueueSize(Queue* qu);//队列长度bool QueueEmpty(Queue* qu);//判断队列是否为空

        //Queue.c

#include"Queue.h"
void QueueInit(Queue* qu)//初始化栈
{qu->_head = qu->_tail = NULL;
}
void QueueDestory(Queue* qu)//摧毁栈
{//确保指针有效assert(qu);QueueNode* cur = qu->_head;while (cur){QueueNode* next = cur->_next;free(cur);}
}
void QueuePush(Queue* qu,QDataType data)//入队
{if (qu->_head == NULL){qu->_head = (QueueNode*)malloc(sizeof(QueueNode));qu->_tail = qu->_head;qu->_head->_next = NULL;qu->_head->_data = data;}else{//尾部入数据QueueNode* cur = qu->_tail;QueueNode* newNode = (QueueNode*)malloc(sizeof(QueueNode));cur->_next = newNode;newNode->_next = NULL;qu->_tail = newNode;newNode->_data = data;}
}
void QueuePop(Queue* qu)//出队
{//队头出数据QueueNode* head = qu->_head;qu->_head = head->_next;free(head);
}
QDataType QueueFront(Queue* qu)//返回队头元素
{return qu->_head->_data;
}
QDataType QueueBack(Queue* qu)//返回队尾元素
{return qu->_tail->_data;
}
size_t QueueSize(Queue* qu)//队列长度
{assert(qu);//确保指针存在QueueNode* cur = qu->_head;size_t size = 0;while (cur){++size;cur = cur->_next;}return size;
}
bool QueueEmpty(Queue* qu)//判断队列是否为空
{return !qu->_head;
}

        //Test.c

#include"BTree.h"
void TestBTreeNode()
{BTreeNode* root = NULL;root = CreatBinaryTree(root);/*PreOrder(root);printf("\n");InOrder(root);printf("\n");PostOrder(root);*///printf("%d\n", BinaryTreeSize(root));printf("%d\n", BinaryTreeLeafSize(root));printf("%d\n", BinarTreelen(root));//LevelOrder(root);printf("%d\n", BinaryTreeComplete(root));printf("%d\n", BinaryTreeLevelKSize(root, 3));BinaryTreeDestory(root);root = NULL;//根节点置空,防止野指针的问题
}
int main()
{TestBTreeNode();}

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

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

相关文章

Linux下 Socket服务器和客户端文件互传

目录 1.项目描述 2.函数准备 2.1 gets函数 2.2 popen函数、fread函数 2.3 access 函数 2.4 exit 函数 2.5 strtok 函数 2.6 chdir函数 3.项目代码 3.1服务器代码 3.2客户端代码 4.问题总结 1.项目描述 基于Soket聊天服务器&#xff0c;实现服务器和客户端的文件传输。…

Mendix如何实现导出文件

刚刚接触Mendix低代码两周&#xff0c;花了一周在b站看初级视频然后考完初级&#xff0c;第二周开始做个列表查询感觉照葫芦画瓢没啥难度。但最近要求写个导出列表数据&#xff0c;在mendix社区翻了翻&#xff0c;这个功能算是常见的。找了mendix官方提供的Docs磕磕盼盼才实现了…

双向交错CCM图腾柱无桥单相PFC学习仿真与实现(4)一些优化总结

前言 上一次说到单相的PFC硬件功能已经实现&#xff0c;THD3.15%满足了国标要求的范围&#xff0c;还是有优化的空间&#xff0c;目前系统设计的是6.6Kw&#xff0c;220V交流输出&#xff0c;400-800V直流输出。目前基本功能完成&#xff0c;但是还有很多细节需要优化&#xf…

科技驱动产业升级:浅谈制造型企业对MES系统的应用

在科技不断进步的背景下&#xff0c;制造型行业也在持续发展&#xff0c;但随之而来的挑战也不断增加。传统的管理方式已经无法满足企业的需求&#xff0c;因此许多制造型企业开始寻找新的管理模式。制造执行系统&#xff08;MES&#xff09;作为先进的制造信息技术之一&#x…

学会这几步,教你1分钟辨出B站优质UP主!

品牌想要投放某UP主&#xff0c;该如何判断UP主是否优质并且同品牌相匹配呢&#xff1f;运用这一套多维度的UP主评估方法 &#xff0c;帮助你高效判断&#xff0c;快来看看具体怎么操作吧&#xff01; 一、up主粉丝涨跌 有些广告主在判断UP主是否值得投放时&#xff0c;会陷入…

9.3.tensorRT高级(4)封装系列-自动驾驶案例项目self-driving-车道线检测

目录 前言1. 车道线检测总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习 tensorRT 高级-自动驾驶案例项目self-driving-车道…

工服穿戴检测联动门禁开关算法

工服穿戴检测联动门禁开关算法通过yolov8深度学习框架模型&#xff0c;工服穿戴检测联动门禁开关算法能够准确识别和检测作业人员是否按照规定进行工服着装&#xff0c;只有当人员合规着装时&#xff0c;算法会发送开关量信号给门禁设备&#xff0c;使门禁自动打开。YOLO的结构…

港陆证券:五日线破位怎么看?

在股票交易中&#xff0c;五日线是个重要的技术指标之一&#xff0c;它能够反映出最近的商场趋势。假如五日线破位&#xff0c;这意味着商场呈现了趋势反转&#xff0c;出资者需求注重趋势改动&#xff0c;并采取相应的出资战略。 首先&#xff0c;咱们来看看五日线破位的原因…

【算法与数据结构】654、LeetCode最大二叉树

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;【算法与数据结构】106、LeetCode从中序与后序遍历序列构造二叉树这两道题有些类似&#xff0c;相关代…

OLED透明屏原彩优势和特点解析:开创显示技术新时代

OLED透明屏 原彩作为一项领先的显示技术&#xff0c;正以其卓越的性能和创新的设计特点引起广泛关注。 本文将通过深入探讨OLED透明屏 原彩的优势和特点、应用领域、技术发展以及未来前景等方面内容&#xff0c;并结合具体数据、报告和行业动态&#xff0c;为读者提供专业可信…

解决DNS服务器未响应错误的方法

​当你将设备连接到家庭网络或具有互联网接入功能的Wi-Fi热点时,由于各种原因,互联网连接可能无法正常工作。本文中的说明适用于Windows 10、Windows 8和Windows 7。 无法连接到DNS服务器的原因 故障的一类与域名系统有关,域名系统是世界各地互联网提供商使用的分布式名称…

W5500-EVB-PICO进行MQTT连接订阅发布教程(十二)

前言 上一章我们用开发板通过SNTP协议获取网络协议&#xff0c;本章我们介绍一下开发板通过配置MQTT连接到服务器上&#xff0c;并且订阅和发布消息。 什么是MQTT&#xff1f; MQTT是一种轻量级的消息传输协议&#xff0c;旨在物联网&#xff08;IoT&#xff09;应用中实现设备…

仿`gRPC`功能实现像调用本地方法一样调用其他服务器方法

文章目录 仿gRPC功能实现像调用本地方法一样调用其他服务器方法 简介单体架构微服务架构RPCgPRC gRPC交互逻辑服务端逻辑客户端逻辑示例图 原生实现仿gRPC框架编写客户端方法编写服务端方法综合演示 仿 gRPC功能实现像调用本地方法一样调用其他服务器方法 简介 在介绍gRPC简介…

【OpenCV入门】第五部分——图像运算

文章结构 掩模图像的加法运算图像的位运算按位与运算按位或运算按位取反运算按位异或运算图像位运算的运用 合并图像加权和覆盖 掩模 当计算机处理图像时&#xff0c;有些内容需要处理&#xff0c;有些内容不需要处理。能够覆盖原始图像&#xff0c;仅暴露原始图像“感兴趣区域…

Myvatis关联关系映射与表对象之间的关系

目录 一、关联关系映射 1.1 一对一 1.2 一对多 1.3 多对多 二、处理关联关系的方式 2.1 嵌套查询 2.2 嵌套结果 三、一对一关联映射 3.1 建表 ​编辑 3.2 配置文件 3.3 代码生成 3.4 编写测试 四、一对多关联映射 五、多对多关联映射 六、小结 一、关联关系映射 …

一文学会K8s集群搭建

环境准备 节点数量&#xff1a;2台虚拟机 centos7硬件配置&#xff1a;master节点内存至少3G&#xff08;2G后面在master节点初始化集群时会报错&#xff0c;内存不够&#xff09;&#xff0c;node节点可以2G&#xff0c;CPU至少2个&#xff0c;硬盘至少30G网络要求&#xff1…

Ant-Design-Pro-V5: ProTable前端导出excel表格。

Prtable表格中根据搜索条件实现excel表格导出。 代码展示&#xff1a; index.jsx import React, { useRef, useState, Fragment, useEffect } from react; import { getLecturerList, lecturerExportExcel } from /services/train/personnel; import { getOrgList, getSelec…

Navicat Premium 16.2.7 for Mac

Navicat Premium 16是一款功能强大的跨平台数据库管理工具&#xff0c;支持多种数据库类型&#xff0c;如MySQL、MariaDB、Oracle、SQLite、PostgreSQL等等。它提供了丰富的数据库管理功能和工具&#xff0c;可以帮助开发人员和数据库管理员快速地创建、管理和维护数据库。 Nav…

stable diffusion实践操作-大模型介绍

本文专门开一节写大模型相关的内容&#xff0c;在看之前&#xff0c;可以同步关注&#xff1a; stable diffusion实践操作 模型下载网站 国内的是&#xff1a;https://www.liblibai.com 国外的是&#xff1a;https://civitai.com&#xff08;科学上网&#xff09; 一、发展历…

自动化驱动程序管理

在部署操作系统时&#xff0c;每次都从下载和分发所需的驱动程序中实现真正的独立性可能是一场艰苦的战斗。特别是具有硬件多样化的环境&#xff0c;并且需要支持新的硬件类型时。借助 OS Deployer&#xff0c;可以对所有端点使用一个映像&#xff0c;无论品牌和型号如何&#…