【C语言】数据结构——链式二叉树实例探究

news2024/12/24 4:05:48

💗个人主页💗
⭐个人专栏——数据结构学习⭐
💫点击关注🤩一起学习C语言💯💫

导读:

我们在前面学习了单链表,顺序表,栈和队列,小堆。
今天我们来学习链式二叉树
关注博主或是订阅专栏,掌握第一消息。

1. 链式二叉树的概念和结构

链式二叉树(Linked Binary Tree)是一种基于链表实现的二叉树结构。在链式二叉树中,每个节点由三个部分组成:数据、左子节点和右子节点。
在这里插入图片描述

1.1 链式二叉树的特点

链式二叉树的特点包括:

  1. 每个节点都有一个数据项,可以是任意类型的数据。
  2. 每个节点都有一个左子节点和一个右子节点。如果某个节点没有左子节点或右子节点,对应的子节点指针就为空。
  3. 子节点可以是空的,也可以是另一个链式二叉树的根节点。这就构成了二叉树的递归结构。

链式二叉树的优点是可以动态地插入和删除节点,不需要预先指定树的大小。
同时,链式二叉树的节点可以随意分配在内存中,不需要连续的存储空间。
缺点是相对于数组实现的二叉树,链式二叉树需要额外的指针来连接节点,因此会占用更多的内存空间。

1.2 链式二叉树的遍历

链式二叉树的遍历方式有三种:前序遍历、中序遍历和后序遍历。

前序遍历先访问根节点,然后按照左子树、右子树的顺序遍历;
中序遍历先访问左子树,然后访问根节点,最后访问右子树;
后序遍历先访问左子树,然后访问右子树,最后访问根节点。

2. 二叉树的代码实现

2.1 创建二叉树

我们先创建一个六个节点的二叉树


typedef int BTDataType;
//typedef char BTDataType;

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

//开辟空间并赋值
TreeNode* BuyTreeNode(int x)
{
    TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
    assert(node);
    node->data = x;
    node->left = NULL;
    node->right = NULL;
    return node;
}
TreeNode* CreateTree()
{
    TreeNode* node1 = BuyTreeNode(7);
    TreeNode* node2 = BuyTreeNode(9);
    TreeNode* node3 = BuyTreeNode(30);
    TreeNode* node4 = BuyTreeNode(25);
    TreeNode* node5 = BuyTreeNode(66);
    TreeNode* node6 = BuyTreeNode(88);
    node1->left = node2;
    node1->right = node4;
    node2->left = node3;
    node4->left = node5;
    node4->right = node6;
    return node1;
}

在这里插入图片描述

2.2 前序遍历

前序遍历:访问根结点的操作发生在遍历其左右子树之前。
**注意:**左节点全部访问完之后才访问右节点。
遇到NULL,则返回,否则继续调用,直到遇到NULL

//前序遍历
void PrevOrder(TreeNode* root)
{
    if (root == NULL)
    {
        printf("NULL ");
        return NULL;
    }
    //先访问根节点
    printf("%d ", root->data);
    //之后访问左节点和右节点
    PrevOrder(root->left);
    PrevOrder(root->right);
}

在这里我们把空值也打印了出来
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.3 中序遍历

中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。
**注意:**是把一个节点的所有左子树访问完之后再去打印值,最后再访问右子树。

//中序遍历
void InOrder(TreeNode* root)
{
    if (root == NULL)
    {
        printf("NULL ");
        return NULL;
    }
    //访问完所有左子树后再打印值
    InOrder(root->left);
    printf("%d ", root->data);
    InOrder(root->right);
}

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

2.4 计算节点个数

计算链式二叉树的节点个数可以通过递归的方式实现。

  1. 若二叉树为空,则节点个数为0。
  2. 若二叉树不为空,则节点个数为根节点的个数加上左子树的节点个数和右子树的节点个数。
  3. 使用递归对左子树和右子树分别计算节点个数。
  4. 返回根节点的个数加上左子树和右子树的节点个数。
// 节点个数
int TreeSize(TreeNode* root)
{
    //如果为空返回0
    if (root == NULL)
    {
        return 0;
    }
    //不为空调用左右节点,每次调用都会加一
    return TreeSize(root->left)
        + TreeSize(root->right) + 1;
}

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

2.5 计算叶子节点的个数

叶子节点是指在树中没有子节点的节点,可以通过遍历树的方式来计算叶子节点的个数。
以下是计算叶子节点个数的递归算法:

  1. 如果树为空,则叶子节点个数为0。
  2. 如果树只有一个节点,则叶子节点个数为1。
  3. 否则,叶子节点个数等于左子树的叶子节点个数加上右子树的叶子节点个数。
// 叶子节点的个数
int TreeLeafSize(TreeNode* root)
{
    if (root == NULL)
    {
        return 0;
    }
    //如果该节点的左节点和右节点都为空
    if (!(root->left) && !(root->right))
    {
        return 1;
    }
    return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}

在这里插入图片描述

2.6 计算树的高度

计算树的高度可以使用递归的方法来完成。一个树的高度可以定义为从根节点到最远叶子节点的边数。

// 树的高度
int TreeHight(TreeNode* root)
{
    if (root == NULL)
    {
        return 0;
    }
    //返回较大的一个
    return fmax(TreeHight(root->left), TreeHight(root->right)) + 1;
}

在这里插入图片描述

2.7 计算树第k层节点个数

树的第k层节点个数取决于树的结构,不同的树的第k层节点个数可能不同。一般情况下,树的第k层节点个数为k层的节点数减去k-1层的节点数。

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

在这里插入图片描述
k=1时,说明到达了k层
在这里插入图片描述

2.8 二叉树查找值为x的节点

二叉树查找值为x的节点可以通过递归来实现,具体步骤如下:

  1. 如果当前节点为空,则返回空。
  2. 如果当前节点的值等于x,则返回当前节点。
  3. 如果该节点的值不等于x,递归在左子树中查找值为x的节点。
  4. 如果该左子树节点的值不等于x,递归在右子树中查找值为x的节点。
TreeNode* TreeFind(TreeNode* root, BTDataType x)
{
    if (root == NULL)
    {
        return NULL;
    }
    if (root->data == x)
    {
        return root;
    }
    //另设记录函数调用返回的值,再判断是否为kong
    TreeNode* ret1 = TreeFind(root->left, x);
    if (ret1)
    {
        return ret1;
    }
    TreeNode* ret2 = TreeFind(root->right, x);
    if (ret2)
    {
        return ret2;
    }
    return NULL;
}

在这里插入图片描述

2.9 通过前序遍历的数组构建二叉树

通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树,通过遍历我们要建立如下效果:
在这里插入图片描述

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
TreeNode* TreeCreate(char* a, int* pi)
{
    if (a[*pi] == '#')
    {
        (*pi)++;
        return NULL;
    }
    TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
    if (root == NULL)
    {
        perror("malloc fail");
        exit(-1);
    }
    root->data = a[(*pi)++];
    root->left = TreeCreate(a, pi);
    root->right = TreeCreate(a, pi);
    return root;
}
int main()
{
    char arr[] = "ABD##E#H##CF##G##";
    int i = 0;
    TreeNode* rootstr = TreeCreate(arr, &i);
    return 0;
}

2.10 层序遍历

链式二叉树的层序遍历可以通过使用队列来实现。具体步骤如下:

  1. 首先,将根节点入队。

  2. 进入循环,直到队列为空。

    • 从队列中取出一个节点,并将其值输出。
    • 如果该节点有左子节点,则将左子节点入队。
    • 如果该节点有右子节点,则将右子节点入队。
  3. 循环结束后,层序遍历完成。

//层序遍历
void LevelOrder(TreeNode* root)
{
    QNode q;
    QueueInit(&q);
    if (root)
    {
        QueuePush(&q, root);
    }
    int levelSize = 1;
    while (!QueueEmpty(&q))
    {
        while (levelSize--)
        {
            TreeNode* front = QueueFront(&q);
            QueuePop(&q);
            printf("%c ", front->data);
            if (front->left)
            {
                QueuePush(&q, front->left);
            }
            if (front->right)
            {
                QueuePush(&q, front->right);
            }
        }
        printf("\n");
        levelSize = QueueSize(&q);
    }
    printf("\n");

    QueueDestroy(&q);
}

在这里插入图片描述

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

2.11 判断一棵树是否是完全二叉树

完全二叉树是指除了最后一层外,其他层的节点都是满的,且最后一层的节点从左到右依次填满。因此,我们可以通过遍历树的节点来判断是否是完全二叉树。

  1. 使用层次遍历的方法遍历树的节点。
  2. 当遇到第一个为空的节点时,停止遍历。
  3. 继续遍历树的节点,如果还存在非空节点,那么该树不是完全二叉树。
  4. 如果遍历完所有节点,都没有发现非空节点,那么该树是完全二叉树。
//判断一棵树是否是完全二叉树
bool TreeComplete(TreeNode* root)
{
    Queue q;
    QueueInit(&q);
    if (root)
    {
        QueuePush(&q, root);
    }
    while (!QueueEmpty(&q))
    {
        TreeNode* front = QueueFront(&q);
        QueuePop(&q);

        if (front == NULL)
        {
            break;
        }

        QueuePush(&q, front->left);
        QueuePush(&q, front->right);
    }
    // 前面遇到空以后,后面还有非空就不是完全二叉树
    while (!QueueEmpty(&q))
    {
        TreeNode* front = QueueFront(&q);
        QueuePop(&q);

        if (front)
        {
            QueueDestroy(&q);
            return false;
        }
    }
    QueueDestroy(&q);
    return true;
}

2.12 二叉树销毁

需要把每一个节点都销毁,值得注意的是,要从最下层的节点开始销毁,而不是根节点

//二叉树销毁
void DestroyTree(TreeNode* root)
{
    if (root == NULL)
    {
        return NULL;
    }
    DestroyTree(root->left);
    DestroyTree(root->right);
    free(root);
}

3. 代码整理

该代码的层序遍历导入了我们之前写的队列

Queue.h

#define _CRT_SECURE_NO_WARNINGS 

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>


// 链式结构:表示队列 
typedef int QDataType;
typedef struct QueueNode
{
	QDataType val;
	struct QueueNode* next;
}QNode;

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

// 初始化队列 
void QueueInit(Queue* pq);

// 销毁队列 
void QueueDestroy(Queue* pq);

// 队尾入队列 
void QueuePush(Queue* pq, QDataType x);

// 队头出队列
void QueuePop(Queue* pq);

// 获取队列头部元素 
QDataType QueueFront(Queue* pq);

// 获取队列队尾元素
QDataType QueueBack(Queue* pq);

// 检测队列是否为空,如果为空返回true,如果非空返回false 
bool QueueEmpty(Queue* pq);

// 获取队列中有效元素个数 
int QueueSize(Queue* pq);

Queue.c

#include "Queue.h"

// 初始化队列 
void QueueInit(Queue* pq)
{
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}

// 销毁队列 
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->phead->next;
	while (cur)
	{
		free(pq->phead);
		pq->phead = cur;
		cur = cur->next;
	}
	cur = NULL;
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}

// 队尾入队列 
void QueuePush(Queue* pq, QDataType x)
{
	//开辟新空间
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->val = x;
	newnode->next = NULL;
	if (pq->ptail == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}

// 队头出队列
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->phead);
	QNode* tmp = pq->phead;
	pq->phead = pq->phead->next;
	free(tmp);
	tmp = NULL;
	if (pq->phead == NULL)
	{
		pq->ptail = NULL;
	}
	pq->size--;
}

// 获取队列头部元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead);
	return pq->phead->val;
}

// 获取队列队尾元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->ptail);
	return pq->ptail->val;
}

// 检测队列是否为空,如果为空返回true,如果非空返回false 
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->size == 0;
}

// 获取队列中有效元素个数 
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}

study.c

#include "Queue.h"

typedef int BTDataType;
//typedef char BTDataType;

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

TreeNode* BuyTreeNode(int x)
{
    TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
    assert(node);
    node->data = x;
    node->left = NULL;
    node->right = NULL;
    return node;
}
TreeNode* CreateTree()
{
    TreeNode* node1 = BuyTreeNode(7);
    TreeNode* node2 = BuyTreeNode(9);
    TreeNode* node3 = BuyTreeNode(30);
    TreeNode* node4 = BuyTreeNode(25);
    TreeNode* node5 = BuyTreeNode(66);
    TreeNode* node6 = BuyTreeNode(88);
    node1->left = node2;
    node1->right = node4;
    node2->left = node3;
    node4->left = node5;
    node4->right = node6;
    return node1;
}

//前序遍历
void PrevOrder(TreeNode* root)
{
    if (root == NULL)
    {
        printf("NULL ");
        return NULL;
    }
    //先访问根节点
    printf("%d ", root->data);
    //之后访问左节点和右节点
    PrevOrder(root->left);
    PrevOrder(root->right);
}

//中序遍历
void InOrder(TreeNode* root)
{
    if (root == NULL)
    {
        printf("NULL ");
        return NULL;
    }
    //访问完所有左子树后再打印值
    InOrder(root->left);
    printf("%d ", root->data);
    InOrder(root->right);
}

// 节点个数
int TreeSize(TreeNode* root)
{
    //如果为空返回0
    if (root == NULL)
    {
        return 0;
    }
    //不为空调用左右节点,每次调用都会加一
    return TreeSize(root->left)
        + TreeSize(root->right) + 1;
}

// 叶子节点的个数
int TreeLeafSize(TreeNode* root)
{
    if (root == NULL)
    {
        return 0;
    }
    //如果该节点的左节点和右节点都为空
    if (!(root->left) && !(root->right))
    {
        return 1;
    }
    return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}

// 树的高度
int TreeHight(TreeNode* root)
{
    if (root == NULL)
    {
        return 0;
    }
    //返回较大的一个
    return fmax(TreeHight(root->left), TreeHight(root->right)) + 1;
}

//树第k层节点个数
int TreeLevelK(TreeNode* root, int k)
{
    assert(k > 0);
    if (root == NULL)
    {
        return 0;
    }
    if (k == 1)
    {
        return 1;
    }
    return TreeLevelK(root->left, k - 1) + 
        TreeLevelK(root->right, k - 1);
}

// 二叉树查找值为x的节点
TreeNode* TreeFind(TreeNode* root, BTDataType x)
{
    if (root == NULL)
    {
        return NULL;
    }
    if (root->data == x)
    {
        return root;
    }
    //另设记录函数调用返回的值,再判断是否为kong
    TreeNode* ret1 = TreeFind(root->left, x);
    if (ret1)
    {
        return ret1;
    }
    TreeNode* ret2 = TreeFind(root->right, x);
    if (ret2)
    {
        return ret2;
    }
    return NULL;
}

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
TreeNode* TreeCreate(char* a, int* pi)
{
    if (a[*pi] == '#')
    {
        (*pi)++;
        return NULL;
    }
    TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
    if (root == NULL)
    {
        perror("malloc fail");
        exit(-1);
    }
    root->data = a[(*pi)++];
    root->left = TreeCreate(a, pi);
    root->right = TreeCreate(a, pi);
    return root;
}

//二叉树销毁
void DestroyTree(TreeNode* root)
{
    if (root == NULL)
    {
        return NULL;
    }
    DestroyTree(root->left);
    DestroyTree(root->right);
    free(root);
}

//层序遍历
void LevelOrder(TreeNode* root)
{
    QNode q;
    //初始化队列
    QueueInit(&q);
    if (root)
    {
        //把根节点入队列
        QueuePush(&q, root);
    }
    //从1开始
    int levelSize = 1;
    while (!QueueEmpty(&q))
    {
        while (levelSize--)
        {
            TreeNode* front = QueueFront(&q);
            QueuePop(&q);
            printf("%c ", front->data);
            //入左子树和右子树
            if (front->left)
            {
                QueuePush(&q, front->left);
            }
            if (front->right)
            {
                QueuePush(&q, front->right);
            }
        }
        printf("\n");
        //获取队列有效数据个数
        levelSize = QueueSize(&q);
    }
    printf("\n");
    QueueDestroy(&q);
}

//判断一棵树是否是完全二叉树
bool TreeComplete(TreeNode* root)
{
    Queue q;
    QueueInit(&q);
    if (root)
    {
        QueuePush(&q, root);
    }
    //遍历入队列
    while (!QueueEmpty(&q))
    {
        TreeNode* front = QueueFront(&q);
        QueuePop(&q);
        if (front == NULL)
        {
            break;
        }
        QueuePush(&q, front->left);
        QueuePush(&q, front->right);
    }
    // 前面遇到空以后,后面还有非空就不是完全二叉树
    while (!QueueEmpty(&q))
    {
        TreeNode* front = QueueFront(&q);
        QueuePop(&q);

        if (front)
        {
            QueueDestroy(&q);
            return false;
        }
    }
    QueueDestroy(&q);
    return true;
}

void Test1()
{
    TreeNode* root = CreateTree();
    printf("前序遍历:\n");
    PrevOrder(root);
    printf("\n");
    printf("中序遍历:\n");
    InOrder(root);
    printf("\n");

    printf("节点个数:%d\n", TreeSize(root));
    printf("叶子节点的个数:%d\n", TreeLeafSize(root));
    printf("树的高度:%d\n", TreeHight(root));
    printf("树第k层节点个数:%d\n", TreeLevelK(root, 3));
    int x = 0;
    printf("请输入想要查找的x值:》");
    scanf("%d", &x);
    printf("查找值为x的节点: %p\n", TreeFind(root, x));
    bool ret = TreeComplete(root);
    if (ret)
    {
        printf("yes\n");
    }
    else
    {
        printf("no\n");
    }
}

void Test2()
{
    char arr[] = "ABD##E#H##CF##G##";
    int i = 0;
    TreeNode* rootstr = TreeCreate(arr, &i);
    LevelOrder(rootstr);
}
int main()
{
    //Test1();
    Test2();
    return 0;
}


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

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

相关文章

WPF仿网易云搭建笔记(7):HandyControl重构

文章目录 专栏和Gitee仓库前言相关文章 新建项目项目环境项目结构 代码结果结尾 专栏和Gitee仓库 WPF仿网易云 Gitee仓库 WPF仿网易云 CSDN博客专栏 前言 最近我发现Material Design UI的功能比较简单&#xff0c;想实现一些比较简单的功能&#xff0c;比如消息提示&#xff0…

抖音直播间websocket礼物和弹幕消息推送可能出现重复的情况,解决办法

在抖音直播间里&#xff0c;通过websocket收到的礼物消息数据格式如下&#xff1a; {common: {method: WebcastGiftMessage,msgId: 7283420150152942632,roomId: 7283413007005207308,createTime: 1695803662805,isShowMsg: True,describe: 莎***:送给主播 1个入团卡,priority…

解决goview栈内存溢出导致打包报错问题

最近搞低代码大屏使用goview打包时遇到问题 报错&#xff1a; vite v4.3.6 building for production... transforming (8931) node_modules\monaco-editor\esm\vs\base\common\navigator.js <--- Last few GCs ---> [24864:000001B515BA39F0] 65979 ms: Scavenge 2002.0…

VueStu01-Vue是什么

1.概念 Vue 是一个 用于构建用户界面 的 渐进式 框架 。 2.构建用户界面 基于数据渲染出用户看到的页面。 3.渐进式 Vue的学习是循序渐进的&#xff0c;可以学一点用一点&#xff0c;不必全部学完才能用。哪怕你只学了 声明式渲染 这一个小部分的内容&#xff0c;你也可以完成…

Eclipse_03_如何加快index速度

1. ini配置文件 -Xms&#xff1a;是最小堆内存大小&#xff0c;也是初始堆内存大小&#xff0c;因为堆内存大小可以根据使用情况进行扩容&#xff0c;所以初始值最小&#xff0c;随着扩容慢慢变大。 -Xmx&#xff1a;是最大堆内存大小&#xff0c;随着堆内存的使用率越来越高&a…

vue内容渲染

内容渲染指令用来辅助开发者渲染DOM元素的文本内容。常用的内容渲染指令有3个 1.v-text 缺点&#xff1a;会覆盖元素内部原有的内容 2.{{}}&#xff1a;插值表达式在实际开发中用的最多&#xff0c;只是内容的占位符&#xff0c;不会覆盖内容 3.v-html&#xff1a;可以把带有标…

SVM —— 理论推导

SVM 支持向量线性可分最大间隔超平面最大间隔超平面的推导支持向量分类间隔的推导最优化问题 对偶问题拉格朗日乘子法强对偶性 SVM 优化软间隔解决问题优化目标及求解 核函数线性不可分核函数的作用常见核函数 SVM 算法优缺点 支持向量机&#xff08;Support Vector Machine&am…

一、Java基础语法

注意&#xff1a; ​ 用记事本打开本文档&#xff0c;格式较差。 ​ 可安装typora软件后再次打开。 ​ 安装包位于&#xff1a;day01\资料\其他软件\阅读笔记的软件\typora-setup-x64.exe day01 - Java基础语法 1. 人机交互 1.1 什么是cmd&#xff1f; 就是在windows操作…

BearPi Std 板从入门到放弃 - 先天神魂篇(7)(RT-Thread 定时器-软件定时器)

简介 RT-Thread 软件定时器的简单使用步骤 创建项目 参考 BearPi RT-Thread项目创建 定时器管理接口 定时器时钟节拍 定时器管理相关函数 定时器类型 #define RT_TIMER_FLAG_ONE_SHOT 0x0 //一次性计时器 #define RT_TIMER_FLAG_PERIODIC 0x2 // 周期性定时器 #…

博特激光:紫外激光打标机在玻璃行业的应用

随着科技的飞速发展&#xff0c;紫外激光打标机在玻璃行业的应用日益广泛。这种高效、高精度的打标设备为玻璃制品的标识和加工带来了革命性的变革&#xff0c;助力企业提升生产效率和产品质量。 ​ ​ 一、玻璃制品标识 紫外激光打标机采用高能量密度的激光束&#xff0c;能够…

Postman接口自动化测试之——批量执行(集合操作)

集合定义&#xff1a;在接口自动化测试过程中将一组请求&#xff08;多条请求&#xff09;保存到一起进行集中管理。方便执行过程中的维护、导出和执行等。 创建集合 在引导页点击“Collection”&#xff0c;或者在“Collection”标签点击图标&#xff1b; 字段解释 集合描述…

初识Redis缓存,一文掌握Redis重要知识文集。

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

LazyIDA源码阅读

LazyIDA是一款IDA插件&#xff0c;项目地址GitHub - L4ys/LazyIDA: Make your IDA Lazy! 外部引用 from __future__ import division from __future__ import print_function from struct import unpack import idaapi import idautils import idcfrom PyQt5.Qt import QAppli…

idea过往各版本下载

idea过往各版本下载 https://www.jetbrains.com/zh-cn/idea/download/other.html

动手学深度学习2 安装环境

pytorch环境安装 1. windows 环境安装2. mac环境安装3. linux环境安装1. 申请云服务器 链接机器--Ubuntu2. 环境配置 4. 不安装环境直接使用colabQA 课程链接&#xff1a; https://www.bilibili.com/video/BV18p4y1h7Dr?p1&vd_sourceeb04c9a33e87ceba9c9a2e5f09752ef8 1.…

STM32----HAL库函数

1.STM32系统框架 1.1 Cortex-M内核&芯片 1.2 F1系统框架 4个主动单元4个被动单元 AHB&#xff1a;高级高性能总线 APH&#xff1a;高级外围总线 其中 1 为 主动单元 &#xff0c; 2为被动单元 总线时钟频率&…

计算机网络(3):数据链路层

数据链路层属于计算机网络的低层。 数据链路层使用的信道主要有以下两种类型&#xff1a; (1)点对点信道。这种信道使用一对一的点对点通信方式。 (2)广播信道。这种信道使用一对多的广播通信方式。广播信道上连接的主机很多&#xff0c;因此必须使用专用的共享信道协议来协调这…

Springboot项目启动前,使用GUI做初始化配置页面并将Log4j2的日志实时显示在GUI上

Springboot项目启动前&#xff0c;使用GUI做初始化配置页面并将Log4j2的日志实时显示在GUI上 效果预览 Mac Os效果图 Windows 10 效果图 需求分析 做这样的一个功能并不适用于所有系统&#xff0c;主要用于交付给用户的产品&#xff0c;这样方便客户自行维护。传统的服务一般…

Scratch:让少儿编程变得简单有趣

在21世纪这个信息化、数字化的时代&#xff0c;编程已经成为一种重要的技能。然而&#xff0c;对于许多孩子来说&#xff0c;编程可能是一种难以理解和掌握的技能。那么&#xff0c;有没有一种方法&#xff0c;可以让孩子们在轻松愉快的环境中学习编程呢&#xff1f;答案是肯定…

2024年电工(初级)证模拟考试题库及电工(初级)理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年电工&#xff08;初级&#xff09;证模拟考试题库及电工&#xff08;初级&#xff09;理论考试试题是由安全生产模拟考试一点通提供&#xff0c;电工&#xff08;初级&#xff09;证模拟考试题库是根据电工&…