数据结构:栈和队列(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️⃣面向对象方法学四、软件生命周期五、结语一、前言 本文将讲述软件工程导论的第一章相关知识点,主…...

02业务流程的定义
1.要想用好业务流程,首先必须得了解流程与认识流程,什么是业务流程。在认识流程之前,首先要理清两个基本概念,业务和流程。 业务指的是:个人的或者摸个机构的专业工作。流程,原本指的是水的路程࿰…...

【后端高阶面经:架构篇】50、数据存储架构:如何改善系统的数据存储能力?
一、数据存储架构设计核心原则 (一)分层存储架构:让数据各得其所 根据数据访问频率和价值,将数据划分为热、温、冷三层,匹配不同存储介质,实现性能与成本的平衡。 热数据层:访问频率>100次/秒。采用Redis集群存储高频访问数据(如用户登录态、实时交易数据),配合…...
mac电脑安装nvm
方案一、常规安装 下载安装脚本:在终端中执行以下命令来下载并运行 NVM 的安装脚本3: bash curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.39.5/install.sh | bash配置环境变量:安装完成后,需要配置环境变量。如…...

OpenGL Chan视频学习-10 Dealing with Errors in OpenGL
bilibili视频链接: 【最好的OpenGL教程之一】https://www.bilibili.com/video/BV1MJ411u7Bc?p5&vd_source44b77bde056381262ee55e448b9b1973 函数网站: docs.gl 说明: 1.之后就不再单独整理网站具体函数了,网站直接翻译会…...

线程池的详细知识(含有工厂模式)
前言 下午学习了线程池的知识。重点探究了ThreadPoolExecutor里面的各种参数的含义。我详细了解了这部分的知识。其中有一个参数涉及工厂模式,我将这一部分知识分享给大家~ 线程池的详细介绍(含工厂模式) 结语 分享到此结束啦。byebye~...

Git 使用规范
Git 使用规范 一、版本控制的核心原则 🧭二、分支策略(Branch Strategy) 🌿2.1 分支类型与命名规范2.2 可视化流程图 三、提交信息规范(Commit Message)✍️3.1 提交格式3.2 Type 类型说明 四、Tag 版本规范…...

关于无法下载Qt离线安装包的说明
不知道出于什么原因考虑,Qt官方目前不提供离线的安装包下载,意味着网上各种文章提供的各种下载地址都失效了,会提示Download from your IP address is not allowed,当然目前可以在线安装,但是据说只提供了从5.15开始的…...

如何最简单、通俗地理解Pytorch?神经网络中的“梯度”是怎么自动求出来的?PyTorch的动态计算图是如何实现即时执行的?
PyTorch是一门科学——现代深度学习工程中的一把锋利利器。它的简洁、优雅、强大,正在让越来越多的AI研究者、开发者深度应用。 1. PyTorch到底是什么?为什么它重要? PyTorch是一个开源的深度学习框架,由Facebook AI Research(FAIR)于2016年发布,它的名字由两个部分组成…...
BPE、WordPiece 与 Unigram:三种主流子词分词算法对比
BPE、WordPiece 与 Unigram:三种主流子词分词算法对比 在构建现代自然语言处理模型时,Tokenizer 是连接文本与模型之间的桥梁。而在 tokenizer 的设计中,BPE(Byte Pair Encoding)、WordPiece 和 Unigram 三种子词&…...
Starrocks 物化视图的实现以及在刷新期间能否读数据
背景 本司在用Starrocks做一些业务上的分析的时候,用到了物化视图,并且在高QPS的情况下,RT也没有很大的波动,所以在此研究一下Starrock的实现,以及在刷新的时候是不是原子性的 本文基于Starrocks 3.3.5 结论 Starro…...