【数据结构与算法】走进数据结构的“时间胶囊”——栈

news2024/11/25 8:14:50

大家好,我是小卡皮巴拉

文章目录

目录

引言

一.栈的基本概念

1.1 定义

1.2 特性

1.3 基本操作

二.栈的实现方式

2.1 顺序栈

2.2 链栈

三.顺序栈的实现

定义顺序栈的结构

初始化

入栈

检查栈是否为空

出栈

销毁

四.链栈的实现

定义链栈的结构

初始化

 入栈

检查栈是否为空

出栈

销毁

兄弟们共勉!!!  


每篇前言

博客主页:小卡皮巴拉 

咱的口号:🌹小比特,大梦想🌹

作者请求:由于博主水平有限,难免会有错误和不准之处,我也非常渴望知道这些错误,恳请大佬们批评斧正。

引言

在数据结构的大家庭中,栈以其独特的“后进先出”特性脱颖而出,就像是一个记录时间流逝的“时间胶囊”。每当有新数据加入时,它就被放置在栈顶,而最早加入的数据则静静地躺在栈底,等待被最后一个取出。

栈不仅是一个简单的数据结构,更是算法设计和程序优化中的得力助手。从函数调用栈的管理到递归问题的求解,栈的身影无处不在。它以其简洁明了的数据操作规则和高效的内存利用方式,成为了程序员们解决复杂问题时的首选工具。

在接下来的篇章中,我们将一起探索栈的奥秘,从定义到特性,再到丰富的应用场景,帮助大家真正掌握这一数据结构的核心知识。

一.栈的基本概念

1.1 定义

栈(Stack)是一种只允许在一端进行插入或删除的线性表。这端被称为栈顶(Top),另一端则被称为栈底(Bottom)。栈遵循后进先出(Last In First Out,LIFO)的原则,即最后插入的元素会第一个被删除。

1.2 特性

  • 后进先出:栈中最后一个插入的元素首先被删除。这是栈最显著的特点,也是它与其他线性表(如数组、链表)的主要区别。

  • 栈顶浮动,栈底固定:栈顶的位置随着元素的入栈和出栈而变化,而栈底则保持不变。

  • 不支持随机访问:栈的结构决定了只能在栈顶进行插入和删除操作,无法直接访问和修改栈中间的元素。

1.3 基本操作

栈的基本操作主要包括以下几种:

  1. 初始化栈:创建一个空栈,并设置栈底指针和栈顶指针。

  2. 判断栈是否为空:检查栈中是否包含元素,若栈为空则返回true,否则返回false。

  3. 入栈操作(Push):将新元素添加到栈顶。若栈未满,则将新元素放入栈中,并更新栈顶指针。

  4. 出栈操作(Pop):从栈顶移除元素。若栈非空,则弹出栈顶元素,并更新栈顶指针。

  5. 读取栈顶元素(GetTop/Peek):返回栈顶元素的值,但不删除它。若栈非空,则返回栈顶元素的值。

  6. 销毁栈:释放栈占用的存储空间。

二.栈的实现方式

栈的实现方式主要有两种:

2.1 顺序栈

利用数组实现,附设一个指针(top)指示当前栈顶元素的位置。顺序栈需要预分配一块连续的存储空间,其优点是访问速度快,但缺点是存在栈满上溢的风险。

2.2 链栈

采用链表实现,通常使用单链表,并规定所有操作都在链表的表头进行。链栈的优点是便于多个栈共享存储空间、不存在栈满上溢的情况,且插入和删除操作的时间复杂度为O(1)。但缺点是需要额外的指针存储空间。

三.顺序栈的实现

定义顺序栈的结构

首先,我们定义了一个名为STDataType的类型别名,它基于int类型。这个类型别名将用于栈中存储的数据元素。

接着,我们定义了一个名为Stack的结构体(通过typedef,我们也可以用ST来引用它)。这个结构体代表了一个栈的数据结构,并包含以下三个成员:

  1. arr:这是一个指向STDataType类型的指针。它用于动态分配数组,以存储栈中的元素。

  2. top:这是一个整型变量,表示栈顶的位置。在栈中,我们通常将数组的最后一个有效元素的位置视为栈顶。注意,这里的top成员变量实际上存储的是栈顶元素的索引(即数组中的位置),而不是指向栈顶元素的指针。因此,栈为空时,top的值通常被初始化为-1或栈的容量减1(取决于栈的实现方式)。

  3. capacity:这是一个整型变量,表示栈的容量,即栈能够存储的最大元素数量。这个值在栈的初始化时被设定,并且决定了为arr成员动态分配多少内存。

函数代码:

typedef int STDataType;
//定义栈的数据结构
typedef struct Stack
{
	STDataType* arr;
	int top;//指向栈顶位置
	int capacity;
}ST;

初始化

STInit函数用于初始化一个栈。它接收一个指向栈的指针ps作为参数。

  1. 检查指针:首先,使用assert确保传入的栈指针ps不是NULL

  2. 设置初始状态

    • 将栈的数组指针ps->arr设置为NULL,表示栈尚未分配存储空间。
    • 将栈顶位置ps->top设置为0,表示栈为空。
    • 将栈容量ps->capacity也设置为0,表示栈当前没有预设容量。

这样,栈就被初始化为一个空栈,准备进行后续的栈操作。

函数代码:

//初始化
void STInit(ST* ps)
{
	assert(ps);
	ps->arr = NULL;
	ps->top = ps->capacity = 0;
}

入栈

StackPush函数用于将一个元素压入栈顶。它接收两个参数:一个指向栈的指针ps和要压入栈的元素x

  1. 检查指针:首先,使用assert确保传入的栈指针ps不是NULL

  2. 检查容量:接着,检查栈是否已满(即栈顶位置ps->top是否等于栈容量ps->capacity)。

    • 如果栈已满,则进行扩容操作。首先计算新的容量newCapacity,如果当前容量为0,则新容量为4(初始容量),否则新容量为当前容量的两倍。
    • 使用realloc函数尝试为栈的数组ps->arr分配新的内存空间。如果realloc失败(返回NULL),则打印错误信息并退出程序。
    • 如果realloc成功,则更新栈的数组指针ps->arr和栈容量ps->capacity
  3. 入栈操作:在确认栈有足够的空间后,将元素x放入栈顶位置(即ps->arr[ps->top]),并将栈顶位置ps->top加1,以指向下一个空位置。

这样,元素x就被成功压入栈顶,栈的栈顶位置和容量(如果需要的话)也得到了更新。

函数代码:

void StackPush(ST* ps, STDataType x)  
{  
    assert(ps); // 确保栈指针有效  
      
    // 检查栈是否已满  
    if (ps->top == ps->capacity)  
    {  
        // 扩容操作  
        int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;  
        STDataType* tmp = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));  
        if (tmp == NULL)  
        {  
            perror("realloc fail!\n");  
            exit(1); // 扩容失败,退出程序  
        }  
        ps->arr = tmp; // 更新栈的数组指针  
        ps->capacity = newCapacity; // 更新栈的容量  
    }  
      
    // 入栈操作  
    ps->arr[ps->top++] = x; // 将元素放入栈顶,并更新栈顶位置  
}

检查栈是否为空

StackEmpty函数用于判断一个栈是否为空。它接收一个指向栈的指针ps作为参数,并返回一个布尔值。

  1. 检查指针:首先,使用assert确保传入的栈指针ps不是NULL

  2. 判断栈是否为空:然后,通过比较栈顶位置ps->top是否等于0来判断栈是否为空。如果ps->top等于0,表示栈中没有元素,栈为空;否则,栈不为空。

  3. 返回结果:最后,根据判断结果返回相应的布尔值。如果栈为空,则返回true(或等价地,返回非零值,但在C语言中通常使用true1来表示真);如果栈不为空,则返回false(或等价地,返回零值)。

函数代码:

#include <stdbool.h> // 包含头文件以支持布尔值  
  
bool StackEmpty(ST* ps)  
{  
    assert(ps); // 确保栈指针有效  
    return ps->top == 0; // 判断栈是否为空,并返回结果  
}

出栈

StackPop函数用于从栈中移除栈顶元素。它接收一个指向栈的指针ps作为参数,并不返回任何值(即返回类型为void)。

  1. 检查栈是否为空:首先,使用assert宏和StackEmpty函数来确保栈不为空。如果栈为空,则StackEmpty(ps)将返回true(或非零值),导致assert失败,并可能终止程序(这取决于assert宏的具体实现和编译器的设置)。这是一种调试时的安全措施,用于防止对空栈进行出栈操作。

  2. 出栈操作:在确认栈不为空后,通过将栈顶位置ps->top减1来实现出栈操作。这实际上是将栈顶指针向下移动一位,从而“移除”了栈顶元素(但请注意,元素的值仍然保留在内存中,只是不再被视为栈的一部分)。

 函数代码:

#include <assert.h> // 包含头文件以支持assert宏  
#include "stack.h"  // 假设StackEmpty函数和ST结构体定义在这个头文件中  
  
void StackPop(ST* ps)  
{  
    assert(!StackEmpty(ps)); // 确保栈不为空  
    --ps->top; // 将栈顶位置减1,实现出栈操作  
}

取栈顶元素

StackTop函数用于获取栈顶元素的值,但不移除该元素。它接收一个指向栈的指针ps作为参数,并返回栈顶元素的值。

  1. 检查栈是否为空:首先,使用assert宏和StackEmpty函数来确保栈不为空。如果栈为空,则StackEmpty(ps)将返回true(或非零值),导致assert失败,可能会终止程序(这取决于assert宏的具体实现和编译器的设置)。这是一种调试时的安全措施,用于防止对空栈进行取栈顶元素操作。

  2. 获取栈顶元素:在确认栈不为空后,通过访问栈数组ps->arr中栈顶位置ps->top的前一个元素(即ps->arr[ps->top - 1])来获取栈顶元素的值。由于栈顶位置ps->top是指向栈中下一个空位置的索引,因此栈顶元素实际上是位于ps->top - 1的索引处。

  3. 返回栈顶元素的值:最后,函数返回栈顶元素的值。

 函数代码:

#include <assert.h> // 包含头文件以支持assert宏  
#include "stack.h"  // 假设StackEmpty函数、ST结构体和STDataType类型定义在这个头文件中  
  
STDataType StackTop(ST* ps)  
{  
    assert(!StackEmpty(ps)); // 确保栈不为空  
    return ps->arr[ps->top - 1]; // 返回栈顶元素的值  
}

销毁

STDestroy函数用于释放栈所占用的内存资源,并将栈结构体成员重置为初始状态。它接收一个指向栈的指针ps作为参数,并不返回任何值(即返回类型为void)。

  1. 释放栈数组内存:首先,函数检查栈数组指针ps->arr是否不为NULL。如果不为NULL,说明栈数组已经分配了内存,因此使用free函数释放这块内存。这是为了防止内存泄漏,即程序不再需要的内存没有被释放回系统。

  2. 重置栈结构体成员:在释放栈数组内存后,函数将栈结构体成员ps->arr重置为NULL,表示栈数组指针不再指向任何有效的内存区域。同时,将栈的容量ps->capacity和栈顶位置ps->top都重置为0,表示栈现在是空的,且没有分配任何内存。

函数代码:

#include <stdlib.h> // 包含头文件以支持free函数  
#include "stack.h"  // 假设ST结构体定义在这个头文件中  
  
void STDestroy(ST* ps)  
{  
    if (ps->arr != NULL)  
        free(ps->arr); // 释放栈数组内存  
  
    ps->arr = NULL;    // 重置栈数组指针为NULL  
    ps->capacity = 0;  // 重置栈容量为0  
    ps->top = 0;       // 重置栈顶位置为0  
}

四.链栈的实现

定义链栈的结构

我们定义了两个主要结构来支持链栈的实现:

链栈节点结构 (StackNode):

  • STDataType data;:存储节点中的数据,STDataType 在此例中为 int 类型。
  • struct StackNode* next;:指向链栈中下一个节点的指针。若当前节点为链栈末尾,则此指针为 NULL

链栈结构 (LinkedStack):

  • StackNode* top;:栈顶指针,指向链栈的顶部节点(即最后压入的节点)。若链栈为空,则此指针为 NULL
  • // int capacity;:对于链栈,由于其容量是动态的(随着节点的添加和删除而变化),因此这个容量字段在此场景中通常不需要。它已被注释掉,表明在链栈的实现中不考虑此字段。

链栈(或链式栈)是基于链表实现的栈数据结构,它不需要预先分配固定大小的内存空间,能够动态地增长和缩小。数据压入(push)时,新节点被添加到栈顶;数据弹出(pop)时,栈顶节点被移除。

函数代码:

// 定义栈的数据类型  
typedef int STDataType;

// 定义链栈的节点结构  
typedef struct StackNode {
    STDataType data;
    struct StackNode* next;
} StackNode;

// 定义链栈的结构,包含栈顶指针和栈的容量(对于链栈,容量通常不是必需的,但这里为了完整性保留)  
typedef struct LinkedStack {
    StackNode* top;
    // int capacity; // 对于链栈,容量是动态的,因此不需要这个字段  
} LinkedStack;

初始化

函数名:initStack

目的:初始化链栈,确保栈顶指针指向NULL,从而表明链栈当前为空。

参数:LinkedStack* stack,这是一个指向链栈结构体的指针,用于访问和修改链栈的状态。

函数体详细解析:

 stack->top = NULL;

  • 这行代码执行了链栈初始化的核心操作。
  • stack->top 是对链栈结构体中栈顶指针成员的访问。
  • 将 stack->top 设置为 NULL 表示链栈当前不包含任何节点,即栈为空。

函数代码:

// 初始化链栈  
void initStack(LinkedStack* stack) {
    stack->top = NULL; // 栈顶指针初始化为NULL,表示空栈  
}

 入栈

函数名:push

目的:将新数据压入链栈中,使其成为栈顶元素。

参数:

  • LinkedStack* stack:指向链栈结构体的指针,用于访问和修改链栈的状态。
  • STDataType data:要压入链栈的数据。

函数体详细解析:

  1. 创建新节点
    • StackNode* newNode = (StackNode*)malloc(sizeof(StackNode));
    • 这行代码通过malloc函数动态分配内存,用于存储新节点。
    • sizeof(StackNode)计算了StackNode结构体所需的内存大小。
    • (StackNode*)是类型转换,将void*类型的malloc返回值转换为StackNode*类型。
  2. 内存分配失败处理
    • 检查newNode是否为NULL,以判断内存分配是否成功。
    • 若内存分配失败,则打印错误信息并退出程序。
  3. 设置新节点的数据
    • newNode->data = data;
    • 将函数参数data的值赋给新节点的data成员。
  4. 链接新节点到链栈
    • newNode->next = stack->top;
    • 将新节点的next指针指向当前的栈顶节点。
    • 这一步实现了链栈的“后进先出”(LIFO)特性,因为新节点被放在了链栈的顶部。
  5. 更新栈顶指针
    • stack->top = newNode;
    • 将栈顶指针指向新节点,完成压栈操作。

函数代码:

// 压栈操作  
void push(LinkedStack* stack, STDataType data) {
    StackNode* newNode = (StackNode*)malloc(sizeof(StackNode)); // 创建新节点  
    if (!newNode) {
        printf("Memory allocation failed\n");
        exit(EXIT_FAILURE);
    }
    newNode->data = data; // 设置新节点的数据  
    newNode->next = stack->top; // 新节点的next指向当前的栈顶节点  
    stack->top = newNode; // 栈顶指针指向新节点  
}

检查栈是否为空

函数名:isEmpty

目的:判断链栈是否为空。

参数:LinkedStack* stack,指向链栈结构体的指针,用于访问链栈的栈顶指针。

函数体详细解析:

  1. 判断链栈是否为空
    • return stack->top == NULL;
    • 这行代码通过比较栈顶指针stack->top是否为NULL来判断链栈是否为空。
    • stack->topNULL,则链栈为空,函数返回1
    • stack->top不为NULL,则链栈不为空,函数返回0

函数代码:

// 判断链栈是否为空  
int isEmpty(LinkedStack* stack) {
    return stack->top == NULL;
}

出栈

函数名称:pop

函数目的:从链栈中移除栈顶元素,并返回该元素的数据。

函数参数:

  • LinkedStack* stack:指向链栈结构体的指针,包含了链栈的栈顶指针和可能的其他管理信息。

函数返回值:

  • STDataType:被移除的栈顶元素的数据。

函数体解析:

  1. 检查链栈是否为空
    • if (isEmpty(stack)) { ... }
      • 调用isEmpty函数检查链栈是否为空。
      • 如果链栈为空,则打印错误信息“Stack underflow”,表示尝试从空栈中出栈。
      • 通过exit(EXIT_FAILURE)终止程序。这是一种错误处理方式,也可以选择返回一个特殊值来表示错误,但这里选择直接退出程序。
  2. 移除栈顶元素
    • StackNode* tempNode = stack->top;
      • 创建一个临时指针tempNode,并将其指向当前的栈顶节点。
    • STDataType poppedData = tempNode->data;
      • 从栈顶节点中获取数据,并将其存储在局部变量poppedData中。
    • stack->top = tempNode->next;
      • 将栈顶指针更新为指向下一个节点,这样原来的栈顶节点就被从链栈中移除了。
  3. 释放内存
    • free(tempNode);
    • 释放之前被移除的栈顶节点的内存。这是内存管理的重要步骤,防止内存泄漏。
  4. 返回数据
    • return poppedData;
      • 返回被移除的栈顶元素的数据。

函数代码:

// 出栈操作  
STDataType pop(LinkedStack* stack) {
    if (isEmpty(stack)) {
        printf("Stack underflow\n");
        exit(EXIT_FAILURE); // 或者返回一个特殊值表示错误,这里选择退出程序  
    }
    StackNode* tempNode = stack->top; // 临时节点指向栈顶节点  
    STDataType poppedData = tempNode->data; // 获取栈顶节点的数据  
    stack->top = tempNode->next; // 栈顶指针指向下一个节点  
    free(tempNode); // 释放栈顶节点的内存  
    return poppedData; // 返回出栈的数据  
}

销毁

函数名称destroyStack

函数目的:释放链栈中所有节点的内存,从而销毁链栈。

函数参数

  • LinkedStack* stack:指向链栈结构体的指针,包含了链栈的栈顶指针和可能的其他管理信息。

函数解析

destroyStack函数通过循环调用pop函数来逐个移除链栈中的节点,并在每次移除节点时释放其内存。这个过程会一直持续到链栈为空。

  1. 循环检查链栈是否为空
    • 使用while (!isEmpty(stack))循环,只要链栈不为空,就继续执行循环体内的操作。
  2. 出栈操作
    • 在循环体内,调用pop(stack)函数。pop函数会移除链栈的栈顶节点,并释放其内存。同时,pop函数还会返回被移除节点的数据,但在destroyStack函数中,我们并不关心这个返回值。
  3. 无需额外销毁操作
    • 由于pop函数已经负责释放了所有节点的内存,因此destroyStack函数本身不需要进行额外的销毁操作。但是,为了保持接口的一致性(例如,与其他数据结构的销毁函数保持类似的签名),destroyStack函数还是被保留了下来。
  4. 函数结束
    • 当链栈为空时,isEmpty(stack)将返回truewhile循环将终止,destroyStack函数也随之结束。此时,链栈中的所有节点都已经被释放,链栈已被销毁。

函数代码:

// 销毁链栈(释放所有节点的内存)  
void destroyStack(LinkedStack* stack) {
    while (!isEmpty(stack)) {
        pop(stack); // 通过出栈操作释放所有节点的内存  
    }
    // 对于链栈,由于我们已经在出栈时释放了所有节点的内存,因此不需要额外的销毁操作  
    // 但为了保持接口的一致性,这里还是保留了这个函数  
}

兄弟们共勉!!!  

码字不易,求个三连

抱拳了兄弟们!

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

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

相关文章

未来汽车驾驶还会有趣吗?车辆动力学系统简史

未来汽车驾驶还会有趣吗&#xff1f;车辆动力学系统简史 本篇文章来源&#xff1a;Schmidt, F., Knig, L. (2020). Will driving still be fun in the future? Vehicle dynamics systems through the ages. In: Pfeffer, P. (eds) 10th International Munich Chassis Symposiu…

数字图像处理的概念(一)

一 何谓数字图像处理 1 图像的概念 图像是对客观存在的物体的一种相似性的、生动的写真或描述。 2 图像的类别 可见光成像和不可见光成像 单波段、多波段和超波段图像 伽马射线成像 主要用途包括核 医学和天文观测 等 。 核医学 a)同位素注射 骨骼扫描图像 b)正电子放射( …

【Docker】安装、镜像、容器

什么是Docker&#xff1f; Docker&#xff1a;是基于Go语言实现的开源项目。 Docker 是一个用于开发、交付和运行应用程序的开放平台。它允许开发人员将应用程序及其依赖包打包到一个可移植的容器中&#xff0c; 然后在任何流行的 Linux 机器上运行。Docker 容器是完全隔离的&…

Openpyxl--学习记录

1.工作表的基本操作 1.1 工作表的新建打开与保存 1.1.1 创建工作簿 from openpyxl import Workbook from pathlib import Pathfile_path Path.home() / "Desktop" / "123.xlsx"# 1.创建工作簿 wb Workbook() # 2.访问默认工作簿 ws wb.active # 3.填充…

pytorh学习笔记——cifar10(六)MobileNet V1网络结构

基础知识储备&#xff1a; 一、深度可分离卷积&#xff08;Depthwise Separable Convolution&#xff09; MobileNet的核心是深度可分离卷积&#xff08;Depthwise Separable Convolution&#xff09;&#xff0c;深度可分离卷积是卷积神经网络&#xff08;CNN&#xf…

低代码开发详解与行业应用指南

低代码开发简化软件开发&#xff0c;助力企业数字化转型。ZohoCreator应用于零售、制造、教育、IT、医疗、房地产等行业&#xff0c;提升效率、降低成本。灵活定价&#xff0c;支持免费试用&#xff0c;助力企业快速实现数字化。 一、低代码开发是什么&#xff1f; 低代码开发…

CSS3 动画相关属性实例大全(三)(columns、filter、flex、flex-basis 、flex-grow、flex-shrink属性)

CSS3 动画相关属性实例大全&#xff08;三) &#xff08;columns、filter、flex、flex-basis 、flex-grow、flex-shrink属性&#xff09; 本文目录&#xff1a; 一、columns属性&#xff08;设置元素的列宽和列数&#xff09; 二、filter属性&#xff08;调整图像、背景和边…

打造充电场站:场地选择与合规运营详解

建设一座充电站需要六步流程&#xff1a;准备工作 → 备案 → 土地审核 → 规划审核 → 电力申请 → 验收确认 一、准备工作 在确定建设前&#xff0c;要考察待选的场地&#xff0c;例如空地、停车场等&#xff0c;与场地所有方签订充电站建设合作协议。根据场地和车流量等实际…

Docker 部署 EMQX 一分钟极速部署

部署 EMQX ( Docker ) [Step 1] : 拉取 EMQX 镜像 docker pull emqx/emqx:latest[Step 2] : 创建目录 ➡️ 创建容器 ➡️ 拷贝文件 ➡️ 授权文件 ➡️ 删除容器 # 创建目录 mkdir -p /data/emqx/{etc,data,log}# 创建容器 docker run -d --name emqx -p 1883:1883 -p 1808…

H7-TOOL的LUA小程序教程第15期:电压,电流,NTC热敏电阻以及4-20mA输入(2024-10-21,已经发布)

LUA脚本的好处是用户可以根据自己注册的一批API&#xff08;当前TOOL已经提供了几百个函数供大家使用&#xff09;&#xff0c;实现各种小程序&#xff0c;不再限制Flash里面已经下载的程序&#xff0c;就跟手机安装APP差不多&#xff0c;所以在H7-TOOL里面被广泛使用&#xff…

在矩池云使用智谱情感语音模型GLM-4-Voice,详细指南

GLM-4-Voice 是智谱 AI 推出的端到端语音模型。GLM-4-Voice 能够直接理解和生成中英文语音&#xff0c;进行实时语音对话&#xff0c;并且能够遵循用户的指令要求改变语音的情感、语调、语速、方言等属性。 本文将详细介绍&#xff0c;如何在GPU算力租赁平台矩池云上快速复现、…

MongoDB安装配置及配置和启动服务

MongoDB 安装配置 附&#xff1a;MongoDB官网下载地址&#xff1a; https://www.mongodb.com/download-center/community 注&#xff1a; 官网可以下载最新版的MongoDB安装包&#xff0c;有MSI安装版和ZIP安装版。我们课堂上使用4.4.4的ZIP安装版。安装版参考博客&#xff1…

使用rust实现类似C#中的Convert数据转换类

// 编写一个模块&#xff08;好比是C#的一个类&#xff09; pub mod Convert {// 定义函数&#xff08;好比C#中的方法&#xff09;pub fn ToInt32(s:&str) -> i32 {s.parse::<i32>().unwrap()}pub fn ToInt64(s:&str) -> Result<i64,std::num::ParseIn…

Maven入门到实践:从安装到项目构建与IDEA集成

目录 1. Maven的概念 1.1 什么是Maven 1.2 什么是依赖管理 1.3 什么是项目构建 1.4 Maven的应用场景 1.5 为什么使用Maven 1.6 Maven模型 2.初识Maven 2.1 Maven安装 2.1.1 安装准备 2.1.2 Maven安装目录分析 2.1.3 Maven的环境变量 2.2 Maven的第一个项目 2.2.1…

AUTOSAR CP 中 BswM 模块功能与使用介绍(2/2)

三、 AUTOSAR BswM 模块详解及 ARXML 示例 BswM 模块的主要功能 BswM&#xff08;Basic Software Mode Manager&#xff09;模块在 AUTOSAR 架构中扮演着模式管理的核心角色。它负责管理车辆的各种模式&#xff08;如启动、运行、停车等&#xff09;&#xff0c;并根据不同的…

stm32入门教程--ADC模拟-数字转换器

ADC&#xff08;Analog-Digital Converter&#xff09;模拟-数字转换器 ADC可以将引脚上连续变化的模拟电压转你换位内存中存储的数字变量&#xff0c;建立模拟电路到数字电路的桥梁。 12位逐次逼近型ADC&#xff0c;1us转换时间 输入电压范围&#xff1a;0-3.3V转换结果范围…

MCK主机加固与防漏扫的深度解析

在当今这个信息化飞速发展的时代&#xff0c;网络安全成为了企业不可忽视的重要议题。漏洞扫描&#xff0c;简称漏扫&#xff0c;是一种旨在发现计算机系统、网络或应用程序中潜在安全漏洞的技术手段。通过自动化工具&#xff0c;漏扫能够识别出系统中存在的已知漏洞&#xff0…

基于大型语言模型的智能网页抓取

Google Gemini 是 Google AI 创建的大型语言模型 (LLM) 系列&#xff0c;可提供最先进的 AI 功能。Gemini 模型包括&#xff1a; Gemini Ultra — 最大、最强大的模型&#xff0c;擅长处理编码、逻辑推理和创意协作等复杂任务。可通过 Gemini Advanced&#xff08;原名 Bard&a…

使用QT绘图控件QCustomPlot绘制波形图

使用QT绘图控件QCustomPlot绘制波形图 下载QCustomPlot 下载QCustomPlot,链接路径 解压之后就能看到源代码了 在Qt中添加QCustomPlot的帮助文档 在Qt Creator的菜单:工具–>选项–>帮助–>文档–>添加qcustomplot\documentation\qcustomplot.qch文件。

《PP-OCRv1》论文精读:PaddleOCR是目前SOTA级别的OCR开源技术(截止2024年10月)

PP-OCR: A Practical Ultra Lightweight OCR System论文地址PP-OCRv2: Bag of Tricks for Ultra Lightweight OCR System论文地址PP-OCRv3: More Attempts for the Improvement of Ultra Lightweight OCR System论文地址PaddleOCR Github OCR工具库 43.5K个star PP-OCRv1由百度…