数据结构:栈和队列(Leetcode20. 有效的括号+225. 用队列实现栈+232. 用栈实现队列)
目录
一.数据结构--栈
1.栈的基本介绍
2.栈的实现
二.数据结构--队列
1.队列的基本介绍
2.队列的实现
三.栈的运用(Leetcode20. 有效的括号+225)
1.问题描述
2.问题分析
题解代码:
四.用两个队列实现栈(225. 用队列实现栈 - 力扣(Leetcode))
题解代码:
五.用两个栈实现队列(232. 用栈实现队列 - 力扣(Leetcode))
题解代码:
一.数据结构--栈
1.栈的基本介绍
栈是一种数据先进后出,后进先出的数据结构:
- 栈一般用数组来实现(用单链表实现的栈缺陷明显:数据的出栈操作时间复杂度为O(N),原因在于要找到表尾数据的前一个数据的地址)
2.栈的实现
总体图解:
栈的头文件:
#pragma once #include <stdio.h> #include <assert.h> #include <stdbool.h> #include <stdlib.h>typedef int STDataType; typedef struct Stack {STDataType * arry; //栈的堆区空间指针int top; //维护栈顶下标,同时记录栈中的元素个数int capacity; //记录栈的容量 }ST;void StackInit(ST* Stack); //栈对象的初始化 STDataType StackTop(ST*Stack); //返回栈顶元素 void StackPush(ST* Stack,STDataType val); //元素入栈 void StackPop(ST* Stack); //元素出栈 int StackSize(ST* Stack); //返回栈对的元素个数的接口; bool StackEmpty(ST* Stack); //判断栈是否为空的接口 void StackDestroy(ST* Stack); //销毁栈
栈初始化接口:
void StackInit(ST* Stack) {assert(Stack);Stack->arry = NULL;Stack->capacity = 0;Stack->top = 0; }
返回栈顶元素的接口:
STDataType StackTop(ST* Stack) {assert(Stack);assert(Stack->top > 0);return Stack->arry[Stack->top - 1]; }返回栈数据个数的接口:
int StackSize(ST* Stack) {assert(Stack);return Stack->top; }判断栈是否为空的接口:
bool StackEmpty(ST* Stack) {assert(Stack);return (Stack->top == 0); }
数据入栈操作接口:
void StackPush(ST* Stack, STDataType val) {assert(Stack);if (Stack->capacity == Stack->top) //检查容量是否足够{int newcapacity = (0 == Stack->capacity) ? 4 : 2 * Stack->capacity;//如果容量为零,则将容量设置为4,其他情况下按照两倍扩容方式增容STDataType* tem = (STDataType*)realloc(Stack->arry, newcapacity*sizeof(STDataType));if (NULL == tem)//判断realloc是否成功{perror("realloc failed:");exit(-1);}Stack->capacity = newcapacity;Stack->arry = tem;}//元素入栈Stack->arry[Stack->top] = val;Stack->top++; }数据出栈操作接口:
void StackPop(ST* Stack) {assert(Stack);assert(Stack->top > 0);Stack->top--; }销毁栈的接口:
void StackDestroy(ST* Stack) {assert(Stack);if (Stack->arry){free(Stack->arry);}Stack->arry = NULL;Stack->capacity = 0;Stack->top = 0; }
二.数据结构--队列
1.队列的基本介绍
队列是一种数据先进先出,后进后出的数据结构.
- 数据只能从队尾入,从队头出
- 队列一般用单链表实现,原因在于队列涉及数据的头删操作,单链表的数据头删操作时间复杂度为O(1).
2.队列的实现
队列总体图解:
队列的头文件:
#pragma once #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <assert.h>typedef int QDataType;typedef struct QueueNode //单链表结构体 {struct QueueNode* next;QDataType data; }QNode;typedef struct Queue //维护队列的结构体 {QNode* head;QNode* tail; }Queue;void QueueInit(Queue* queue); //队列的初始化接口 void QueueDestroy(Queue* queue); //销毁队列的接口 void QueuePush(Queue* queue,QDataType val); //数据入队接口 void QueuePop(Queue* queue); //数据出队接口 QDataType QueueFront(Queue* queue); //返回队头数据接口 QDataType QueueBawck(Queue* queue); //返回队尾数据接口 int QueueSize(Queue* queue); //返回队列数据个数的接口 bool QueueEmpty(Queue* queue); //判断队列是否为空的接口
队列的初始化接口:
void QueueInit(Queue* queue) //队列初始化 {assert(queue);queue->head = NULL;queue->tail = NULL; }
返回队头数据的接口:
QDataType QueueFront(Queue* queue) //返回队列头部数据 {assert(queue);assert(queue->head);return queue->head->data; }返回队尾数据的接口:
QDataType QueueBawck(Queue* queue) //返回队列尾部数据 {assert(queue);assert(queue->tail);return queue->tail->data; }返回队列数据个数的接口:
int QueueSize(Queue* queue) //返回队列节点个数 {assert(queue);int count = 0;QNode* tem = queue->head;while(tem){count++;tem = tem->next;}return count; }判断队列是否为空的接口:
bool QueueEmpty(Queue* queue) //判断队列是否为空 {assert(queue);return (NULL == queue->head); }
数据入队接口:
![]()
void QueuePush(Queue* queue,QDataType val) //链表尾插数据(数据从队列尾入队) {assert(queue);QNode* NewNode = (QNode*)malloc(sizeof(QNode));//申请堆区链表节点if (NULL == NewNode){perror("malloc failed:");exit(-1);}NewNode->data = val;NewNode->next = NULL;if (NULL == queue->tail) //链表为空时的数据插入操作{assert(NULL == queue->head);queue->tail = NewNode;queue->head = NewNode;}else //链表非空时的数据插入操作{queue->tail->next = NewNode;queue->tail = NewNode;} }数据出队的接口:
void QueuePop(Queue* queue) //删去链表头节点(数据从队列头部出队) {assert(queue);assert(queue->head && queue->tail);QNode* Next = queue->head->next;free(queue->head);queue->head = Next;if (NULL == queue->head) //若删去的是链表的最后一个元素,则要将尾指针也置空{queue->tail = NULL;} }
销毁队列的接口:
void QueueDestroy(Queue* queue) //销毁链表(队列) {assert(queue);QNode* tem = queue->head;while (tem){QNode* Next = tem->next;free(tem);tem = Next;}queue->head = NULL;queue->head = NULL; }
三.栈的运用(Leetcode20. 有效的括号+225)
20. 有效的括号 - 力扣(Leetcode)
1.问题描述
给定一个只包括
'(' ,')' ,'{' ,'}' ,'[' ,']'的字符串s,判断字符串是否有效。有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
示例:
输入:s = "()[]{}" 输出:true
C题解接口:
bool isValid(char * s) {}
2.问题分析
从左向右遍历字符串的情况下的括号匹配思路:
- 由于在遍历字符串时,我们无法确定当前的左括号会和哪一个右括号匹配,因此匹配的思路应该是先找到第一个右括号,然后再向前寻找相应的左括号,若匹配失败则返回false,若匹配成功则继续寻找下一个右括号重复上述过程,直到结束
- 暴力匹配算法动画解析:
- 根据上面的分析可知暴力匹配法的时间复杂度为O(N^2)
然而本题如果使用辅助栈来求解,则可以达到用空间来换取时间效率的目的。
基本思路如下:
- 用一个指针遍历字符串,每当遇到左括号,我们就将其压入栈中
- 每当遇到右括号,我们就将其与栈顶括号进行匹配,若匹配失败则说明字符串不满足条件,接口返回false,若匹配成功则弹出栈顶元素,并继续遍历字符串重复上述步骤直到找到'\0'则接口返回true
- 算法动画图解:
![]()
我们可以将实现好的栈(本期第一节中)用于解题(顺便还可以验证我们栈的实现有没有bug)
题解代码:
用于题解的栈:
typedef char STDataType; typedef struct Stack {STDataType * arry; //栈的堆区空间指针int top; //维护栈顶下标,同时记录栈中的元素个数int capacity; //记录栈的容量 }ST;void StackInit(ST* Stack) {assert(Stack);Stack->arry = NULL;Stack->capacity = 0;Stack->top = 0; }STDataType StackTop(ST* Stack) {assert(Stack);assert(Stack->top > 0);return Stack->arry[Stack->top - 1]; }void StackPush(ST* Stack, STDataType val) {assert(Stack);if (Stack->capacity == Stack->top) //检查容量是否足够{int newcapacity = (0 == Stack->capacity) ? 4 : 2 * Stack->capacity;STDataType* tem = (STDataType*)realloc(Stack->arry, newcapacity*sizeof(STDataType));if (NULL == tem){perror("realloc failed:");exit(-1);}Stack->capacity = newcapacity;Stack->arry = tem;}Stack->arry[Stack->top] = val;Stack->top++; }void StackPop(ST* Stack) {assert(Stack);assert(Stack->top > 0);Stack->top--; }int StackSize(ST* Stack) {assert(Stack);return Stack->top; }bool StackEmpty(ST* Stack) {assert(Stack);return (Stack->top == 0); }void StackDestroy(ST* Stack) {assert(Stack);if (Stack->arry){free(Stack->arry);}Stack->arry = NULL;Stack->capacity = 0;Stack->top = 0; }两个辅助判断接口代码:
//判断指针指向的括号是否为右括号的接口bool CheckRightQutoe(const char quote) //左括号返回true,有括号返回false{if('{' == quote || '(' == quote || '[' == quote){return true;}else{return false;}}//判断两个括号是否匹配的接口bool JudgeMatch(const char right,const char left){if(('}' == right && '{' == left) || (']' == right && '[' == left) || (')' == right && '(' == left) ){return true;}return false;}题解接口代码:
bool isValid(char * s) {ST ans;StackInit(&ans); //创建一个栈int lenth = strlen(s); //字符串有效字符个数为奇数直接返回falseif(lenth % 2 == 1) {return false;}char * tem = s; //tem用于遍历字符串while('\0' != *tem){if(CheckRightQutoe(*tem)) //遇到右括号则入栈{StackPush(&ans,*tem);}else //遇到左括号则与栈顶右括号匹配{if(StackEmpty(&ans) || !JudgeMatch(*tem,StackTop(&ans))){return false; //匹配前注意判断栈是否为空}StackPop(&ans); //匹配完后弹出栈顶括号 }tem ++;}if(!StackEmpty(&ans)) //栈为空说明全部括号都完成了匹配{return false;}return true; }
- 该方法充分利用了栈数据后进先出的特点
- 算法的时间复杂度为O(N)
四.用两个队列实现栈(225. 用队列实现栈 - 力扣(Leetcode))
本题并没有什么实际意义,求解它的目的仅仅在于加深对栈和队列这两种数据结构的理解
- 用两个队列实现数据的先进后出
题解接口:
typedef struct {} MyStack;//创建MyStack结构体 MyStack* myStackCreate() {}//向MyStack两个队列成员中的非空队列中插入数据 //(若两个队列都为空则向任意一个队列插入数据都可以) void myStackPush(MyStack* obj, int x) {}//删除栈顶元素(同时返回栈顶元素的值) int myStackPop(MyStack* obj) {}//栈顶的数据其实就是非空队列尾的数据 int myStackTop(MyStack* obj) {}//返回栈顶的数据 bool myStackEmpty(MyStack* obj) {}//销毁栈 void myStackFree(MyStack* obj) {}
我们可以给自己设置一个规定:用队列实现的'栈'的接口中,我们只能使用队列的标准操作接口来操作'栈'中的元素的进出.
- 本题我们利用本期第二节实现好的队列来实现栈
用两个队列实现栈的数据结构总体图解:
两个队列实现一个栈的结构体的定义:
typedef struct {Queue queue1;Queue queue2; } MyStack;
数据入'栈'接口:
void myStackPush(MyStack* obj, int x)
- 向MyStack两个队列成员中的非空队列中插入数据
- (若两个队列都为空则向任意一个队列插入数据都可以)
![]()
//向MyStack两个队列成员中的非空队列中插入数据 //(若两个队列都为空则向任意一个队列插入数据都可以) void myStackPush(MyStack* obj, int x) {if(!QueueEmpty(&(obj->queue1))){QueuePush(&(obj->queue1),x);}else{QueuePush(&(obj->queue2),x);} }
数据出栈接口:
int myStackPop(MyStack* obj)
数据出栈过程动画图解:
//删除栈顶元素(同时返回栈顶元素的值) int myStackPop(MyStack* obj) {int ret = 0;//将非空队列里面的(除了队尾的元素)移到另外一个空队列中if(!QueueEmpty(&(obj->queue1)) && QueueEmpty(&(obj->queue2))){while(obj->queue1.head != obj->queue1.tail) //转移数据{QueuePush(&(obj->queue2),(obj->queue1).head->data);QueuePop(&(obj->queue1)); }ret = QueueFront(&(obj->queue1)); //记录要弹出的数据QueuePop(&(obj->queue1)); //弹出数据}else{while(obj->queue2.head != obj->queue2.tail) //转移数据{QueuePush(&(obj->queue1),(obj->queue2).head->data);QueuePop(&(obj->queue2));}ret = QueueFront(&(obj->queue2)); //记录要弹出的数据QueuePop(&(obj->queue2)); //弹出数据}return ret; //返回被弹出的数据 }
- 通过两个队列的交互我们便完成了数据的先进后出
题解代码:
用于题解的队列:
typedef int QDataType;typedef struct QueueNode //队列链表节点结构体 {struct QueueNode* next;QDataType data; }QNode;typedef struct Queue //维护队列的结构体 {QNode* head;QNode* tail; }Queue;void QueueInit(Queue* queue); //队列初始化 void QueueDestroy(Queue* queue); //销毁链表(队列) void QueuePush(Queue* queue,QDataType val); //链表尾插数据(数据从队列尾入队) void QueuePop(Queue* queue); //删去链表头节点(数据从队列头部出队) QDataType QueueFront(Queue* queue); //返回队列头部数据 QDataType QueueBawck(Queue* queue); //返回队列尾部数据 int QueueSize(Queue* queue); //返回队列节点个数 bool QueueEmpty(Queue* queue); //判断队列是否为空void QueueInit(Queue* queue) //队列初始化 {assert(queue);queue->head = NULL;queue->tail = NULL; } void QueueDestroy(Queue* queue) //销毁链表(队列) {assert(queue);QNode* tem = queue->head;while (tem) //逐个节点释放链表{QNode* Next = tem->next;free(tem);tem = Next;}queue->head = NULL;queue->head = NULL; }void QueuePush(Queue* queue,QDataType val) //链表尾插数据(数据从队列尾入队) {assert(queue);QNode* NewNode = (QNode*)malloc(sizeof(QNode));if (NULL == NewNode) //在堆区申请节点空间{perror("malloc failed:");exit(-1);}NewNode->data = val;NewNode->next = NULL;if (NULL == queue->tail) //注意判断队列是否为空队列并分类讨论完成元素插入{assert(NULL == queue->head);queue->tail = NewNode; //队列为空时tail和head指向同一个节点queue->head = NewNode;}else{queue->tail->next = NewNode; //队列非空时令tail指向队尾数据queue->tail = NewNode;} }void QueuePop(Queue* queue) //删去链表头节点(数据从队列头部出队) {assert(queue);assert(queue->head && queue->tail);QNode* Next = queue->head->next;free(queue->head);queue->head = Next;if (NULL == queue->head) //注意判断完成删除元素后队列是否变为空队列{queue->tail = NULL;} }QDataType QueueFront(Queue* queue) //返回队列头部数据 {assert(queue);assert(queue->head);return queue->head->data; } QDataType QueueBawck(Queue* queue) //返回队列尾部数据 {assert(queue);assert(queue->tail);return queue->tail->data; }int QueueSize(Queue* queue) //返回队列节点个数 {assert(queue);int count = 0;QNode* tem = queue->head;while(tem) //计算节点个数{count++;tem = tem->next;}return count; }bool QueueEmpty(Queue* queue) //判断队列是否为空 {assert(queue);return (NULL == queue->head); }题解的栈:
typedef struct {Queue queue1;Queue queue2; } MyStack;//创建MyStack结构体 MyStack* myStackCreate() {MyStack * tem = (MyStack *)malloc(sizeof(MyStack));if(NULL == tem){perror("malloc failed:");exit(-1);}QueueInit(&(tem->queue1));QueueInit(&(tem->queue2));return tem; }//向MyStack两个队列成员中的非空队列中插入数据 //(若两个队列都为空则向任意一个队列插入数据都可以) void myStackPush(MyStack* obj, int x) {if(!QueueEmpty(&(obj->queue1))){QueuePush(&(obj->queue1),x);}else{QueuePush(&(obj->queue2),x);} }//删除栈顶元素(同时返回栈顶元素的值) int myStackPop(MyStack* obj) {int ret = 0;//将非空队列里面的(除了队尾的元素)移到另外一个空队列中if(!QueueEmpty(&(obj->queue1)) && QueueEmpty(&(obj->queue2))){while(obj->queue1.head != obj->queue1.tail) //转移数据{QueuePush(&(obj->queue2),(obj->queue1).head->data);QueuePop(&(obj->queue1)); }ret = QueueFront(&(obj->queue1)); //记录要弹出的数据QueuePop(&(obj->queue1)); //弹出数据}else{while(obj->queue2.head != obj->queue2.tail) //转移数据{QueuePush(&(obj->queue1),(obj->queue2).head->data);QueuePop(&(obj->queue2));}ret = QueueFront(&(obj->queue2)); //记录要弹出的数据QueuePop(&(obj->queue2)); //弹出数据}return ret; //返回被弹出的数据 }//栈顶的数据其实就是非空队列尾的数据 int myStackTop(MyStack* obj) {if(!QueueEmpty(&(obj->queue1))){return obj->queue1.tail->data;}else{return obj->queue2.tail->data;} }//返回栈顶的数据 bool myStackEmpty(MyStack* obj) {return QueueEmpty(&(obj->queue1)) && QueueEmpty(&(obj->queue2)); }//销毁栈 void myStackFree(MyStack* obj) {QueueDestroy(&(obj->queue1));QueueDestroy(&(obj->queue2));free(obj);obj = NULL; }
五.用两个栈实现队列(232. 用栈实现队列 - 力扣(Leetcode))
思路图解:
题解代码:
typedef struct {ST PushStack;ST PopStack; } MyQueue;MyQueue* myQueueCreate() //队列初始化接口 {MyQueue* tem = (MyQueue *)malloc(sizeof(MyQueue));if(NULL == tem){perror("malloc failed:");exit(-1);}StackInit(&(tem->PushStack));StackInit(&(tem->PopStack));return tem; }void myQueuePush(MyQueue* obj, int x) {StackPush(&(obj->PushStack),x);//数据入队 }int myQueuePop(MyQueue* obj) {assert(!StackEmpty(&(obj->PushStack)) || !StackEmpty(&(obj->PopStack)));//数据出队前保证队列不为空if(StackEmpty(&(obj->PopStack))) //PopStack为空则要将PushStack数据转移进来{while(!StackEmpty(&(obj->PushStack))){StackPush(&(obj->PopStack),StackTop(&(obj->PushStack)));//将PushStack栈顶数据压入PopStack栈中StackPop(&(obj->PushStack));//完成数据转移后弹出PushStack的栈顶数据}}int ret = StackTop(&(obj->PopStack)); //记录队头元素StackPop(&(obj->PopStack)); //元素出队return ret; //返回队头元素 }int myQueuePeek(MyQueue* obj) {assert(!StackEmpty(&(obj->PushStack)) || !StackEmpty(&(obj->PopStack)));//保证队列不为空if(StackEmpty(&(obj->PopStack))) //PopStack为空则要将PushStack数据转移进来{while(!StackEmpty(&(obj->PushStack))){StackPush(&(obj->PopStack),StackTop(&(obj->PushStack)));//将PushStack栈顶数据压入PopStack栈中StackPop(&(obj->PushStack));//完成数据转移后弹出PushStack的栈顶数据}}return StackTop(&(obj->PopStack));//返回PopStack栈顶元素作为队列队头元素 }bool myQueueEmpty(MyQueue* obj) {return StackEmpty(&(obj->PopStack)) && StackEmpty(&(obj->PushStack));//判断队列是否为空 }void myQueueFree(MyQueue* obj) {StackDestroy(&(obj->PopStack));StackDestroy(&(obj->PushStack));free(obj);obj = NULL; }
- 题解中我们运用的是本期第一节中实现好的栈

相关文章:
数据结构:栈和队列(Leetcode20. 有效的括号+225. 用队列实现栈+232. 用栈实现队列)
目录 一.数据结构--栈 1.栈的基本介绍 2.栈的实现 二.数据结构--队列 1.队列的基本介绍 2.队列的实现 三.栈的运用(Leetcode20. 有效的括号225) 1.问题描述 2.问题分析 题解代码: 四.用两个队列实现栈(225. 用队列实现栈 - 力扣(Leetcode&a…...
22.2.19周赛双周赛(贪心、记忆化搜索...)
文章目录双周赛98[6359. 替换一个数字后的最大差值](https://leetcode.cn/problems/maximum-difference-by-remapping-a-digit/)[6361. 修改两个元素的最小分数](https://leetcode.cn/problems/minimum-score-by-changing-two-elements/)贪心排序[6360. 最小无法得到的或值](ht…...
2023最新软件测试面试题(带答案)
1. 请自我介绍一下(需简单清楚的表述自已的基本情况,在这过程中要展现出自信,对工作有激情,上进,好学) 面试官您好,我叫###,今年26岁,来自江西九江,就读专业是电子商务,毕…...
【C++】类型转换方法
本篇博客让我们来见识一下C中新增的类型转换方法 文章目录1.C语言中类型转换2.C中的强制类型转换2.1 static_cast2.2 reinterpret_cast2.3 const_castvolatile关键字2.4 dynamic_cast3.C强制类型转换的作用4.RTTI1.C语言中类型转换 在C语言中,类型转换有下面两种形…...
100亿级订单怎么调度,来一个大厂的极品方案
背景 超时处理,是一个很有技术难度的问题。 所以很多的小伙伴,在写简历的时候,喜欢把这个技术难题写在简历里边, 体现自己高超的技术水平。 在40岁老架构师 尼恩的读者交流群(50)中,尼恩经常指导大家 优化简历。 最…...
C++性能白皮书
最近看完了《C性能白皮书》,这本书列出了一些性能优化的思路,不过只是一些指引,没有讲具体细节,我整理出了其中的关键点分享给大家: 硬件篇 作为一个程序员,想要性能优化,最好要了解些硬件&…...
华为OD机试 - 黑板上色 | 机试题算法思路 【2023】
最近更新的博客 华为OD机试 - 简易压缩算法(Python) | 机试题算法思路 【2023】 华为OD机试题 - 获取最大软件版本号(JavaScript) 华为OD机试 - 猜字谜(Python) | 机试题+算法思路 【2023】 华为OD机试 - 删除指定目录(Python) | 机试题算法思路 【2023】 华为OD机试 …...
如何在六秒内吸引观众的注意力
根据《2022国民专注力洞察报告》显示,当代人的连续专注时长,已经从2000年的12秒,下降到了现在的8秒。对于这个事实你可能难以相信,实际上这意味着,大多数互联网用户跳到一些页面上时,可能眼皮都不眨一下就离…...
FreeRTOS与UCOSIII任务状态对比
FreeRTOS任务状态 1、运行态 正在运行的任务,正在使用处理器的任务。 单核处理器中任何时候都有且只有一个任务处于运行态。 2、就绪态 已经准备就绪(非阻塞或挂起),可以立即运行但还没有运行的任务。 正在等待比自己高优先级…...
小程序 npm sill idealTree buildDeps 安装一直没反应
目录 一、问题 二、解决 1、删除.npmsrc 、清除缓存 2、更换镜像源 3、最终检测 一、问题 记录:今天npm 一直安装不成功 显示:sill idealTree buildDeps 我的版本: 我百度到换镜像源安装方法,但我尝试后,依然…...
GPT系列详解:初代GPT
本文详细解读了OpenAI公司在2018年6月发布的论文《Improving Language Understanding by Generative Pre-Training》,它其中介绍的算法也就是后来人们说的GPT。本文借鉴了李沐的这个视频,感兴趣的同学可以移步观看大神的讲解。 目录引言GPT方法无监督预训…...
为什么要使用数据库
数据保存在内存优点:存取速度快缺点:数据不能永久保存数据保存在文件优点:数据永久保存缺点:1)速度比内存操作慢,频繁的IO操作。2)查询数据不方便数据保存在数据库1)数据永久保存2&a…...
【单目标优化算法】海鸥优化算法(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
筑基六层 —— 整型提升及实用调式技巧
目录 一.修炼必备 二. 整型提升 三.实用调式技巧 一.修炼必备 1.入门必备:VS2019社区版,下载地址:Visual Studio 较旧的下载 - 2019、2017、2015 和以前的版本 (microsoft.com) 2.趁手武器:印象笔记/有道云笔记 3.修炼秘籍&…...
后端前端文件传输2中传出模式
base64文件传输 app.route(/download, methods[get]) def hello_as(): # 数据 id request.args.get("id") cur g.db.cursor() cur.execute(fselect name,grade,commentNum,cityName,sceneryThemeName from dataList where cityId? , (id,)) …...
【ZOJ 1067】Color Me Less 题解(vector+开方)
问题 颜色缩减是从一组离散颜色到较小颜色的映射。这个问题的解决方案需要在标准的24位RGB颜色空间中执行这样的映射。输入由十六个RGB颜色值的目标集合和要映射到目标集合中最接近的颜色的任意RGB颜色集合组成。为了我们的目的,RGB颜色被定义为有序三元组ÿ…...
凌恩生物经典文章:孟德尔诞辰200周年,Nature Genetics礼献豌豆高质量精细图谱
本期为大家分享的文章是2022年发表在《Nature Genetics》上的一篇文章“Improved pea reference genome and pan-genome highlight genomic features and evolutionary characteristics”,作者通过结合三代pacbio测序、染色体构象捕获(Hi-C)测…...
进程间通信(二)/共享内存
⭐前言:在前面的博文中分析了什么的进程间通信和进程间通信的方式之一:管道(匿名管道和命名管道)。接下来分析第二种方式:共享内存。 要实现进程间通信,其前提是让不同进程之间看到同一份资源。所谓共享内存…...
电路模型和电路定律——“电路分析”
各位CSDN的uu们你们好呀,今天小雅兰的内容是我这学期的专业课噢,首先就学习了电路模型和电路定律,包括电路和电路模型、电流和电压的参考方向、电功率和能量、电路元件、电阻元件、电压源和电流源、基尔霍夫定律。那么现在,就让我…...
软件工程 | 第一章:软件工程学概述
软件工程学概述一、前言二、软件危机1.典型表现2.产生原因3.消除危机途径三、软件工程1.概述2.软件本质特征3.软件工程基本原理4.软件工程方法学1️⃣传统方法学2️⃣面向对象方法学四、软件生命周期五、结语一、前言 本文将讲述软件工程导论的第一章相关知识点,主…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...















题解代码: