【初阶数据结构】5.栈和队列
文章目录
- 1.栈
- 1.1 概念与结构
- 1.2 栈的实现
- 2.队列
- 2.1 概念与结构
- 2.2 队列的实现
- 3.栈和队列算法题
- 3.1 有效的括号
- 3.2 用队列实现栈
- 3.3 用栈实现队列
- 3.4 设计循环队列
1.栈
1.1 概念与结构
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO
(Last In First Out
)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。
栈底层结构选型
栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。
1.2 栈的实现
Stack.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>//定义栈的结构
typedef int STDataType;
typedef struct Stack {STDataType* arr;int capacity;//栈的空间大小int top;//栈顶
}ST;//栈的初始化
void STInit(ST* ps);//栈的销毁
void STDestory(ST* ps);//栈顶---入数据,出数据
//入数据
void StackPush(ST* ps, STDataType x);
//出数据
void StackPop(ST* ps);//取栈顶元素
STDataType StackTop(ST* ps);//获取栈中有效元素个数
int STSize(ST* ps);//判断栈是否为空
bool StackEmpty(ST* ps);
Stack.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Stack.h"//栈的初始化
void STInit(ST* ps) {assert(ps);ps->arr = NULL;ps->capacity = ps->top = 0;
}//栈的销毁
void STDestory(ST* ps) {assert(ps);if (ps->arr) {free(ps->arr);}ps->arr = NULL;ps->top = ps->capacity = 0;
}//栈顶---入数据,出数据
//入数据
void StackPush(ST* ps, STDataType x) {assert(ps);//1.判断空间是否足够if (ps->capacity == ps->top) {int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;//增容STDataType* tmp = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));if (tmp == NULL) {perror("relloc fail!");exit(1);}ps->arr = tmp;ps->capacity = newCapacity;}//空间足够ps->arr[ps->top++] = x;
}//出数据
void StackPop(ST* ps) {assert(ps);assert(!StackEmpty(ps));//栈为空报错--ps->top;
}//判断栈是否为空
bool StackEmpty(ST* ps) {assert(ps);return ps->top == 0;
}//获取栈中有效元素个数
int STSize(ST* ps){assert(ps);return ps->top;
}//取栈顶元素
STDataType StackTop(ST* ps) {assert(ps);assert(!StackEmpty(ps));return ps->arr[ps->top - 1];
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Stack.h"void STTest() {ST st;STInit(&st);//StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);printf("size: %d\n", STSize(&st));//循环出栈,直到栈为空while (!StackEmpty(&st)) {STDataType data = StackTop(&st);printf("%d ", data);//出栈StackPop(&st);}printf("size: %d\n", STSize(&st));////STDestory(&st);
}int main() {STTest();return 0;
}
2.队列
2.1 概念与结构
概念:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
队列底层结构选型
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
2.2 队列的实现
Queue.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>//定义队列结构
typedef int QDataType;typedef struct QueueNode {QDataType data;struct QueueNode* next;
}QueueNode;typedef struct Queue {QueueNode* phead;//队头:删QueueNode* ptail;//队尾:插int size;//保存队列有效数据个数
}Queue;//初始化队列
void QueueInit(Queue* pq);// 入队列,队尾
void QueuePush(Queue* pq, QDataType x);// 出队列,队头
void QueuePop(Queue* pq);//队列判空
bool QueueEmpty(Queue* pq);//取队头数据
QDataType QueueFront(Queue* pq);//取队尾数据
QDataType QueueBack(Queue* pq);//队列有效元素个数
int QueueSize(Queue* pq);//销毁队列
void QueueDestroy(Queue* pq);
Queue.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Queue.h"//初始化队列
void QueueInit(Queue* pq) {assert(pq);pq->phead = pq->ptail = NULL;pq->size = 0;
}// 入队列,队尾
void QueuePush(Queue* pq, QDataType x) {assert(pq);//申请新结点QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));if (newnode == NULL) {perror("malloc fail!");exit(1);}newnode->data = x;newnode->next = NULL;if (pq->phead == NULL) {//判断队列是否为空pq->phead = pq->ptail = newnode;}else {//队列不为空pq->ptail->next = newnode;pq->ptail = newnode;}pq->size++;//入一次,size++ 一次
}//队列判空
bool QueueEmpty(Queue* pq) {assert(pq);return (pq->phead == NULL) && (pq->ptail == NULL);
}// 出队列,队头
void QueuePop(Queue* pq) {assert(pq);assert(!QueueEmpty(pq));//只有一个结点的情况,避免ptail变成野指针if (pq->ptail == pq->phead) {free(pq->phead);pq->phead = pq->ptail = NULL;}else {//删除队头元素QueueNode* next = pq->phead->next;free(pq->phead);pq->phead = next;}--pq->size;//出一次,size-- 一次
}//取队头数据
QDataType QueueFront(Queue* pq) {assert(pq);assert(!QueueEmpty(pq));//判断队列不为空return pq->phead->data;
}//取队尾数据
QDataType QueueBack(Queue* pq) {assert(pq);assert(!QueueEmpty(pq));//判断队列不为空return pq->ptail->data;
}//队列有效元素个数
int QueueSize(Queue* pq) {assert(pq);/*int size = 0;QueueNode* pcur = pq->phead;while (pcur) {size++;pcur = pcur->next;//复杂度O(n)}*/return pq->size;//复杂度O(1)
}//销毁队列
void QueueDestroy(Queue* pq) {assert(pq);assert(!QueueEmpty(pq));//判断队列不为空,空队列不需要销毁QueueNode* pcur = pq->phead;while (pcur) {QueueNode* Next = pcur->next;free(pcur);pcur = Next;}pq->phead = pq->ptail = NULL;pq->size = 0;
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Queue.h"void QueueTest01() {Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);//QueuePop(&q);printf("head:%d\n", QueueFront(&q));printf("tail:%d\n", QueueBack(&q));printf("size:%d\n", QueueSize(&q));QueueDestroy(&q);//QueuePop(&q);//QueuePop(&q);//QueuePop(&q);//QueuePop(&q);QueuePop(&q);
}int main() {QueueTest01();return 0;
}
3.栈和队列算法题
3.1 有效的括号
点击链接答题
思路:
定义一个指针
ps
遍历字符串若
ps
遍历到的字符为左括号,入栈若
ps
遍历到的字符为右括号,取栈顶元素与ps
进行比较,
栈顶元素 匹配 *ps
,出栈,ps++
栈顶元素 不匹配 *ps
,返回false
代码:
//定义栈的结构
typedef char STDataType;
typedef struct Stack {STDataType* arr;int capacity;//栈的空间大小int top;//栈顶
}ST;//栈的初始化
void STInit(ST* ps) {assert(ps);ps->arr = NULL;ps->capacity = ps->top = 0;
}//栈的销毁
void STDestory(ST* ps) {assert(ps);if (ps->arr) {free(ps->arr);}ps->arr = NULL;ps->top = ps->capacity = 0;
}//栈顶---入数据,出数据
//入数据
void StackPush(ST* ps, STDataType x) {assert(ps);//1.判断空间是否足够if (ps->capacity == ps->top) {int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;//增容STDataType* tmp = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));if (tmp == NULL) {perror("relloc fail!");exit(1);}ps->arr = tmp;ps->capacity = newCapacity;}//空间足够ps->arr[ps->top++] = x;
}//判断栈是否为空
bool StackEmpty(ST* ps) {assert(ps);return ps->top == 0;
}//出数据
void StackPop(ST* ps) {assert(ps);assert(!StackEmpty(ps));//栈为空报错--ps->top;
}//获取栈中有效元素个数
int STSize(ST* ps){assert(ps);return ps->top;
}//取栈顶元素
STDataType StackTop(ST* ps) {assert(ps);assert(!StackEmpty(ps));return ps->arr[ps->top - 1];
}bool isValid(char* s) {ST st;//初始化STInit(&st);//遍历字符串schar* ps = s;while(*ps != '\0'){//左括号,入栈if(*ps == '(' || *ps == '[' || *ps == '{'){StackPush(&st, *ps);}else{//右括号,和栈顶元素比较是否匹配//栈为空,直接返回falseif(StackEmpty(&st)){return false;}//栈不为空才能取栈顶元素char ch = StackTop(&st);if((*ps == ')' && ch == '(')|| (*ps == ']' && ch == '[')|| (*ps == '}' && ch == '{') ){StackPop(&st);} else{//不匹配STDestory(&st);return false;}}ps++;}bool ret = StackEmpty(&st) == true;//如果为空,返回true//销毁STDestory(&st);return ret;
}
3.2 用队列实现栈
点击链接答题
思路:
出栈:找不为空的队列,将
size-1
个数据导入到另一个队列中。入栈:往不为空队列里面插入数据
取栈顶元素:
例如:
两个队列:
- Q1:
1 2 3
- Q2:
NULL
如果是栈的话:
- 插入
1 2 3
- 出栈一次
- 插入4
- 全部出栈
得到:
3 4 2 1
将
Q1
里面的1 2
出栈到Q2
,把3
取出来,此时Q1
为NULL
取出了3
往
Q2
里面插入4
,此时Q2
为1 2 4
将
Q2
里面的1 2
出栈到Q1
,此时Q2
为4
,把4
取出来,此时Q2
为NULL
取出了3 4
将
Q1
里面的1
出栈到Q2
,把2
取出来 ,此时Q1
为NULL
取出了3 4 2
将
Q2
里面的1
取出来取出了3 4 2 1
代码:
//定义队列结构
typedef int QDataType;typedef struct QueueNode {QDataType data;struct QueueNode* next;
}QueueNode;typedef struct Queue {QueueNode* phead;//队头:删QueueNode* ptail;//队尾:插int size;//保存队列有效数据个数
}Queue;//初始化队列
void QueueInit(Queue* pq) {assert(pq);pq->phead = pq->ptail = NULL;pq->size = 0;
}// 入队列,队尾
void QueuePush(Queue* pq, QDataType x) {assert(pq);//申请新结点QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));if (newnode == NULL) {perror("malloc fail!");exit(1);}newnode->data = x;newnode->next = NULL;if (pq->phead == NULL) {//判断队列是否为空pq->phead = pq->ptail = newnode;}else {//队列不为空pq->ptail->next = newnode;pq->ptail = newnode;}pq->size++;//入一次,size++ 一次
}//队列判空
bool QueueEmpty(Queue* pq) {assert(pq);return (pq->phead == NULL) && (pq->ptail == NULL);
}// 出队列,队头
void QueuePop(Queue* pq) {assert(pq);assert(!QueueEmpty(pq));//只有一个结点的情况,避免ptail变成野指针if (pq->ptail == pq->phead) {free(pq->phead);pq->phead = pq->ptail = NULL;}else {//删除队头元素QueueNode* next = pq->phead->next;free(pq->phead);pq->phead = next;}--pq->size;//出一次,size-- 一次
}//取队头数据
QDataType QueueFront(Queue* pq) {assert(pq);assert(!QueueEmpty(pq));//判断队列不为空return pq->phead->data;
}//取队尾数据
QDataType QueueBack(Queue* pq) {assert(pq);assert(!QueueEmpty(pq));//判断队列不为空return pq->ptail->data;
}//队列有效元素个数
int QueueSize(Queue* pq) {assert(pq);return pq->size;//复杂度O(1)
}//销毁队列
void QueueDestroy(Queue* pq) {assert(pq);//这里允许pq为空// assert(!QueueEmpty(pq));//判断队列不为空,空队列不需要销毁QueueNode* pcur = pq->phead;while (pcur) {QueueNode* Next = pcur->next;free(pcur);pcur = Next;}pq->phead = pq->ptail = NULL;pq->size = 0;
}//两个队列来实现栈
typedef struct {Queue q1;//队列1Queue q2;//队列2
} MyStack;//STInit
MyStack* myStackCreate() {MyStack* pst = (MyStack*)malloc(sizeof(MyStack));QueueInit(&pst->q1);QueueInit(&pst->q2);return pst;
}//Push入栈
void myStackPush(MyStack* obj, int x) {//往不为空的队列中插入数据if(!QueueEmpty(&obj->q1)){//如果q1不为空,执行这个QueuePush(&obj->q1,x);//往队列q1里面插入x}else{//如果q2不为空,执行这个QueuePush(&obj->q2,x);//往队列q2里面插入x}
}//Pop出栈
int myStackPop(MyStack* obj) {//找不为空的队列Queue* empQ = &obj->q1;//定义q1为空Queue* noneQ = &obj->q2;//定义q2为非空if(!QueueEmpty(&obj->q1)){//如果q1不为空,执行这个noneQ = &obj->q1;//q1是非空队列empQ = &obj->q2;//q2是空队列}//将不为空队列中size-1个数据导入到空队列中while(QueueSize(noneQ) > 1){//循环结束的判断,是只剩下一个数据int front = QueueFront(noneQ);//取队头数据QueuePush(empQ,front);//往空队列q2里面插入队头元素QueuePop(noneQ);//把非空队列q1里面的队头元素拿出来,这样下次循环出来的队头元素就不会重复了}//非空队列中只剩下一个数据------要出栈的数据int pop = QueueFront(noneQ);//把要取出的数据存起来QueuePop(noneQ);//将数据出队列,让q1变成空队列return pop;//返回要取出的数据
}//取栈顶元素:找不为空的队列,取队尾元素
//不出栈
int myStackTop(MyStack* obj) {if(!QueueEmpty(&obj->q1)){//q1不为空return QueueBack(&obj->q1);//取队尾数据}else{//q2不为空return QueueBack(&obj->q2);//取队尾数据}
}//判断栈是否为空
//也就是判断两个队列是否为空
bool myStackEmpty(MyStack* obj) {//栈是空的,返回 true ;否则,返回 false 。return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}//栈的销毁
//也就是判断两个队列的销毁
void myStackFree(MyStack* obj) {QueueDestroy(&obj->q1);//销毁q1QueueDestroy(&obj->q2);//销毁q2//因为MyStack* myStackCreate()里面有个指针pst,所以我们还要销毁指针objfree(obj);//销毁指向栈的指针obj = NULL;
}/*** Your MyStack struct will be instantiated and called as such:* MyStack* obj = myStackCreate();* myStackPush(obj, x);* int param_2 = myStackPop(obj);* int param_3 = myStackTop(obj);* bool param_4 = myStackEmpty(obj);* myStackFree(obj);
*/
3.3 用栈实现队列
点击链接答题
思路:
定义两个栈:
pushST
(入数据)和popST
(出数据)假设我们要在队列里放
123
,出队列123
我们先在
pushST
里面放进去1 2 3
然后把
pushST
里面的数据拿到popST
里面,依次是3 2 1
然后把
1
提取出来,把2
提取出来,把3
提取出来.
如果我们先在
pushST
里面放进去1 2 3
然后把
pushST
里面的数据拿到popST
里面,依次是3 2 1
然后在
pushST
里面放进去4
然后把
popST
里面的1
提取出来,把2
提取出来,把3
提取出来.然后把
pushST
里面的数据4
拿到popST
里面然后把
4
提取出来
入队:往
pushST
中插入数据出队:判断
popST
是否为空,不为空直接pop
,为空的话将pushST
导入到popST
中再pop
取队头:跟出队一样,但这里只取数据,不
pop
数据
代码:
//定义栈的结构
typedef char STDataType;
typedef struct Stack {STDataType* arr;int capacity;//栈的空间大小int top;//栈顶
}ST;//栈的初始化
void STInit(ST* ps) {assert(ps);ps->arr = NULL;ps->capacity = ps->top = 0;
}//栈的销毁
void STDestory(ST* ps) {assert(ps);if (ps->arr) {free(ps->arr);}ps->arr = NULL;ps->top = ps->capacity = 0;
}//栈顶---入数据,出数据
//入数据
void StackPush(ST* ps, STDataType x) {assert(ps);//1.判断空间是否足够if (ps->capacity == ps->top) {int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;//增容STDataType* tmp = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));if (tmp == NULL) {perror("relloc fail!");exit(1);}ps->arr = tmp;ps->capacity = newCapacity;}//空间足够ps->arr[ps->top++] = x;
}//判断栈是否为空
bool StackEmpty(ST* ps) {assert(ps);return ps->top == 0;
}//出数据
void StackPop(ST* ps) {assert(ps);assert(!StackEmpty(ps));//栈为空报错--ps->top;
}//获取栈中有效元素个数
int STSize(ST* ps){assert(ps);return ps->top;
}//取栈顶元素
STDataType StackTop(ST* ps) {assert(ps);assert(!StackEmpty(ps));return ps->arr[ps->top - 1];
}//
typedef struct {ST pushST;ST popST;
} MyQueue;//队列的初始化
MyQueue* myQueueCreate() {MyQueue* pst = (MyQueue*)malloc(sizeof(MyQueue));STInit(&pst->pushST);STInit(&pst->popST);return pst;
}//往pushST中插入数据
void myQueuePush(MyQueue* obj, int x) {StackPush(&obj->pushST,x);
}//删除数据
//1.检查popST是否为空,不为空直接出,为空pushST导入到popST,再出数据
int myQueuePop(MyQueue* obj) {if(StackEmpty(&obj->popST)){//如果popST为空//导数据while(!StackEmpty(&obj->pushST)){//如果pushST非空StackPush(&obj->popST, StackTop(&obj->pushST));//把取到的栈顶元素导入进popSTStackPop(&obj->pushST);}}//取栈顶,删除栈顶元素并返回栈顶数据int top = StackTop(&obj->popST);//储存删除的栈顶元素StackPop(&obj->popST);return top;//返回删除的栈顶元素
}//取队头元素
int myQueuePeek(MyQueue* obj) {if(StackEmpty(&obj->popST)){//如果popST为空//导数据while(!StackEmpty(&obj->pushST)){//如果pushST非空StackPush(&obj->popST, StackTop(&obj->pushST));//把取到的栈顶元素导入进pushSTStackPop(&obj->pushST);}}//取栈顶,删除栈顶元素并返回栈顶数据return StackTop(&obj->popST);//返回删除的栈顶元素}//判断队列是否为空
bool myQueueEmpty(MyQueue* obj) {return StackEmpty(&obj->pushST) && StackEmpty(&obj->popST);
}//队列的销毁
//就是两个栈的销毁
void myQueueFree(MyQueue* obj) {STDestory(&obj->pushST);STDestory(&obj->popST);free(obj);obj = NULL;
}/*** Your MyQueue struct will be instantiated and called as such:* MyQueue* obj = myQueueCreate();* myQueuePush(obj, x);* int param_2 = myQueuePop(obj);* int param_3 = myQueuePeek(obj);* bool param_4 = myQueueEmpty(obj);* myQueueFree(obj);
*/
3.4 设计循环队列
点击链接答题
思路:
循环队列,空间固定。
这里我们可以用数组来实现循环队列。
如何判断队列是否为满?
多申请一块空间
(rear+1)%(k+1) == front
如何判断队列是否为空?
rear == front
代码:
//定义循环队列的结构
typedef struct {int* arr;//定义数组int front;//定义头int rear;//定义尾int capacity;//定义一个变量保存数组空间大小
} MyCircularQueue;//循环队列的初始化
MyCircularQueue* myCircularQueueCreate(int k) {//定义一个指针,动态申请一块空间,指向循环队列MyCircularQueue* pst = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));//底层数组申请k+1个整型空间pst->arr = (int*)malloc(sizeof(int)*(k+1));pst->front = pst->rear = 0;pst->capacity = k;//把k保存起来return pst;//返回指向循环队列的指针
}//判断队列是否满了
bool myCircularQueueIsFull(MyCircularQueue* obj) {//(rear+1)%(k+1) == front 就满了return (obj->rear+1)%(obj->capacity+1) == obj->front;
}//入队列
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {//队列满了就不能插入数据if(myCircularQueueIsFull(obj)){return false;//说明插入失败}//队列没满,可以插入数据obj->arr[obj->rear++] = value;//插入一个数据rear++obj->rear %= obj->capacity + 1;//如果rear跑到队尾了,就通过取余回到队头return true;//说明插入成功
}//判断队列是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return obj->rear == obj->front;
}//出队列
bool myCircularQueueDeQueue(MyCircularQueue* obj) {//队列为空if(myCircularQueueIsEmpty(obj)){return false;//表示删除失败}//队列不为空obj->front++;obj->front %= obj->capacity + 1;//如果front跑到队尾了,就通过取余回到队头return true;//表示删除成功
}//取队头元素
int myCircularQueueFront(MyCircularQueue* obj) {//如果队列为空if(myCircularQueueIsEmpty(obj)){return -1;//如果队列为空,返回 -1 }//如果队列不为空return obj->arr[obj->front];
}//取队尾元素
int myCircularQueueRear(MyCircularQueue* obj) {//如果队列为空if(myCircularQueueIsEmpty(obj)){return -1;//如果队列为空,返回 -1 }//如果队列不为空int prev = obj->rear-1;//prev是rear前一个位置if(obj->rear == 0){prev = obj->capacity;//如果rear是处在arr[0],那么prev在arr[k]}return obj->arr[prev];
}//循环队列的销毁
//就是顺序表的销毁
void myCircularQueueFree(MyCircularQueue* obj) {free(obj->arr);free(obj);obj = NULL;
}/*** Your MyCircularQueue struct will be instantiated and called as such:* MyCircularQueue* obj = myCircularQueueCreate(k);* bool param_1 = myCircularQueueEnQueue(obj, value);* bool param_2 = myCircularQueueDeQueue(obj);* int param_3 = myCircularQueueFront(obj);* int param_4 = myCircularQueueRear(obj);* bool param_5 = myCircularQueueIsEmpty(obj);* bool param_6 = myCircularQueueIsFull(obj);* myCircularQueueFree(obj);
*/
循环队列的概念与结构
实际中还有一种特殊的队列叫循环队列,环形队列首尾相连成环,环形队列可以使用数组实现,也可以使用循环链表实现
思考:队列满的情况下,为什么 Q.rear 不存储数据?
为了能使用
Q.rear = Q.front
来区别是队空还是队满,我们常常认为出现左图时的情况即为队满的情况此时:
rear+1=front
相关文章:
![](https://i-blog.csdnimg.cn/direct/c742c0ebafea4af08ee037a5c69d5a3f.png#pic_center)
【初阶数据结构】5.栈和队列
文章目录 1.栈1.1 概念与结构1.2 栈的实现2.队列2.1 概念与结构2.2 队列的实现3.栈和队列算法题3.1 有效的括号3.2 用队列实现栈3.3 用栈实现队列3.4 设计循环队列 1.栈 1.1 概念与结构 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操…...
![](https://i-blog.csdnimg.cn/direct/f53b9a8aeef94191a61ed2e88243164d.png)
高通Android 12 设置Global属性为null问题
1、最近在做app调用framework.jar需求,尝试在frameworks/base/packages/SettingsProvider/res/values/defaults.xml增加属性 <integer name"def_xxxxx">1</integer> 2、在frameworks\base\packages\SettingsProvider\src\com\android\provide…...
![](https://www.ngui.cc/images/no-images.jpg)
Xcode代码静态分析:构建无缺陷代码的秘诀
Xcode代码静态分析:构建无缺陷代码的秘诀 在软件开发过程中,代码质量是至关重要的。Xcode作为Apple的官方集成开发环境(IDE),提供了强大的代码静态分析工具,帮助开发者在编写代码时发现潜在的错误和问题。…...
![](https://i-blog.csdnimg.cn/direct/09a90bb619ed4a65a321e34aa23bbd5c.png)
Qt各个版本安装的保姆级教程
文章目录 前言Qt简介下载Qt安装包安装Qt找到Qt的快捷方式总结 前言 Qt是一款跨平台的C图形用户界面应用程序开发框架,广泛应用于桌面软件、嵌入式软件、移动应用等领域。Qt的强大之处在于其高度的模块化和丰富的工具集,可以帮助开发者快速、高效地构建出…...
![](https://i-blog.csdnimg.cn/direct/f829641dd7284cf484c4dfc2a265489b.png)
数学建模--优劣解距离法TOPSIS
目录 简介 TOPSIS法的基本步骤 延伸 优劣解距离法(TOPSIS)的历史发展和应用领域有哪些? 历史发展 应用领域 如何准确计算TOPSIS中的理想解(PIS)和负理想解(NIS)? TOPSIS方法在…...
![](https://www.ngui.cc/images/no-images.jpg)
Springboot开发之 Excel 处理工具(三) -- EasyPoi 简介
引言 Springboot开发之 Excel 处理工具(一) – Apache POISpringboot开发之 Excel 处理工具(二)-- Easyexcel EasyPoi是一款基于 Apache POI 的高效 Java 工具库,专为简化 Excel 和 Word 文档的操作而设计。以下是对…...
![](https://img-blog.csdnimg.cn/direct/df413fc3bbea46f7962bc7fe31fa6a01.png)
【BUG】已解决:python setup.py bdist_wheel did not run successfully.
已解决:python setup.py bdist_wheel did not run successfully. 目录 已解决:python setup.py bdist_wheel did not run successfully. 【常见模块错误】 解决办法: 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主…...
![](https://www.ngui.cc/images/no-images.jpg)
Java 中如何支持任意格式的压缩和解压缩
👆🏻👆🏻👆🏻关注博主,让你的代码变得更加优雅。 前言 Hutool 是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率…...
![](https://i-blog.csdnimg.cn/direct/861a10ec65384a9f8e94f92936c8e6d2.png#pic_center)
从零开始实现大语言模型(八):Layer Normalization
1. 前言 Layer Normalization是深度学习实践中已经被证明非常有效的一种解决梯度消失或梯度爆炸问题,以提升神经网络训练效率及稳定性的方法。OpenAI的GPT系列大语言模型使用Layer Normalization对多头注意力模块,前馈神经网络模块以及最后的输出层的输入张量做变换,使shap…...
![](https://i-blog.csdnimg.cn/direct/21747583d3af4fd594a82e5bf705c379.png)
<数据集>混凝土缺陷检测数据集<目标检测>
数据集格式:VOCYOLO格式 图片数量:7353张 标注数量(xml文件个数):7353 标注数量(txt文件个数):7353 标注类别数:6 标注类别名称:[exposed reinforcement, rust stain, Crack, Spalling, Efflorescence…...
![](https://i-blog.csdnimg.cn/direct/2b7f5c9c2e5e472cb8b16aff60ebe598.png)
【LabVIEW作业篇 - 3】:数组相加、for循环创建二位数组、数组练习(求最大最小值、平均值、中位数、提取范围内的数据、排序)
文章目录 数组相加for循环实现直接使用加函数 for循环创建二位数组数组练习 数组相加 要求:用两种方法实现两个数组相加 for循环实现 在前面板中分别创建两个数值类型的一维数组,并设置相应的值,然后在程序框图中创建一个for循环ÿ…...
![](https://i-blog.csdnimg.cn/direct/9e172ca7bef449ca9d5f0cae3060d351.png)
Unity动画系统(4)
6.3 动画系统高级1-1_哔哩哔哩_bilibili p333- 声音组件添加 using System.Collections; using System.Collections.Generic; using UnityEngine; public class RobotAnimationController : MonoBehaviour { [Header("平滑过渡时间")] [Range(0,3)] publ…...
![](https://img-blog.csdnimg.cn/img_convert/a8627bf62e77638b4e93f30ca8ba83a6.webp?x-oss-process=image/format,png)
React基础学习-Day08
React基础学习-Day08 React生命周期(旧)(新)(函数组件) (旧) 在 React 16 版本之前,React 使用了一套不同的生命周期方法。这些生命周期方法在 React 16 中仍然可以使用…...
![](https://i-blog.csdnimg.cn/direct/d3ea5412ca564ff3a128ae57359b95c1.png)
Flowable的学习一
今日项目用到了Flowable。简单记录下。 学习中 参考了网上资料: 工作流-Activiti7-基础讲解_activity工作流-CSDN博客 https://juejin.cn/post/7158342433615380517 flowable实战(九)flowable数据库表中流程实例、活动实例、任务实例三者…...
![](https://img-blog.csdnimg.cn/img_convert/a1704348dad26a01a070ec27be75f427.png)
django-vue-admin项目运行
文本主要对django-vue-admin项目进行了简要介绍,并且对前后端进行了源码安装和运行。在此基础上可作为管理系统二次开发的基础框架。 一.django-vue-admin简介和安装 1.简介 django-vue-admin项目是基于RBAC模型权限控制的中小型应用的基础开发平台,采…...
![](https://i-blog.csdnimg.cn/direct/7d6d6c292e754100aee045a0f65f5908.png)
4. docker镜像、Dockerfile
docker镜像、Dockerfile 一、docker镜像1、镜像介绍2、镜像核心技术 二、Dockerfile定制镜像1、Dockerfile使用流程1.1 编写Dockerfile1.2、构建镜像1.3 创建容器测试镜像定制操作 2、Dockerfile常用指令 三、部署springcloud微服务架构的商品秒杀项目1、部署项目需要的基础服务…...
![](https://www.ngui.cc/images/no-images.jpg)
智能水果保鲜度检测:基于YOLO和深度学习的完整实现
引言 水果新鲜程度直接影响其口感和营养价值。为了提高水果品质管理的效率和准确性,本文介绍了一种基于深度学习的水果新鲜程度检测系统。该系统包括用户界面,利用YOLO(You Only Look Once)v8/v7/v6/v5模型进行水果新鲜程度检测&…...
![](https://www.ngui.cc/images/no-images.jpg)
C#中implicit 关键字的使用:隐式转换操作符
在 C# 中,implicit 关键字用于定义隐式转换操作符。隐式转换操作符允许自动将一种数据类型转换为另一种类型,而无需显式地调用转换方法或进行类型转换。下面将详细介绍 implicit 关键字的定义和使用。 1. 隐式转换操作符 定义 隐式转换操作符可以定义在一个类或结构体中,…...
![](https://www.ngui.cc/images/no-images.jpg)
Laravel表单验证:自定义规则的艺术
Laravel表单验证:自定义规则的艺术 在Web应用开发中,表单验证是确保数据完整性和安全性的关键步骤。Laravel提供了一个强大且灵活的验证系统,允许开发者定义自定义验证规则,以满足特定的业务需求。本文将详细介绍如何在Laravel中…...
![](https://i-blog.csdnimg.cn/direct/d929d1756a884015ad414db936598e28.png)
Linux中的环境变量
一、环境变量定义 一般是指在操作系统中用来指定操作系统运行环境的一些参数 如:我们在编写C/C代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但 是照样可以链接成功,生成可执行程序,…...
![](https://i-blog.csdnimg.cn/direct/f9c34aad50264c26bfafbd1806a9f021.jpeg)
关于集成网络变压器的RJ45网口
集成网络变压器的RJ45网口是一种将网络变压器与RJ45接口集成在一起的网络连接解决方案。这种集成设计具有多项优势,使其在现代网络设备中得到广泛应用。 优势与特点 1. **空间节省**:集成设计减少了组件数量和连接线缆长度,有助于节省设备内…...
![](https://img-blog.csdnimg.cn/img_convert/ff6e41335d46ab7f85ca41ef83430482.png)
JMX 反序列化漏洞
前言 前段时间看到普元 EOS Platform 爆了这个洞,Apache James,Kafka-UI 都爆了这几个洞,所以决定系统来学习一下这个漏洞点。 JMX 基础 JMX 前置知识 JMX(Java Management Extensions,即 Java 管理扩展࿰…...
![](https://i-blog.csdnimg.cn/direct/53c2443105354142b4d9651d01be5994.png)
【Qt】常用控件 Q widget的enabled属性,geometry属性
Qt是一个实现图形化程序的程序。为了便于我们开发,Qt为我们提供了许多“控件”。我们需要熟悉并掌握这些控件的使用。 一.什么是控件 控件是构成⼀个图形化界⾯的基本要素. 示例一: 像上述⽰例一中的,按钮,列表视图,树形视图,单⾏输⼊框,多⾏输⼊框,滚动…...
![](https://i-blog.csdnimg.cn/direct/2f7377ebdefb40cc98ac2c9e946e669a.png)
Unity3d开发google chrome的dinosaur游戏
游戏效果 游戏中: 游戏中止: 一、制作参考 如何制作游戏?【15分钟】教会你制作Unity小恐龙游戏!新手15分钟内马上学会!_ unity教学 _ 制作游戏 _ 游戏开发_哔哩哔哩_bilibili 二、图片资源 https://download.csdn.…...
![](https://img-blog.csdnimg.cn/img_convert/652e9554aad58952d520ab4f798bd617.jpeg)
【数据分享】2013-2022年我国省市县三级的逐日SO2数据(excel\shp格式\免费获取)
空气质量数据是在我们日常研究中经常使用的数据!之前我们给大家分享了2000——2022年的省市县三级的逐日PM2.5数据和2013-2022年的省市县三级的逐日CO数据(均可查看之前的文章获悉详情)! 本次我们分享的是我国2013——2022年的省…...
![](https://i-blog.csdnimg.cn/direct/2267ce0528ea46d4a3a0c66fcef1b998.png)
【玩转C语言】第五讲--->数组-->一维和多维深度理解
🔥博客主页🔥:【 坊钰_CSDN博客 】 欢迎各位点赞👍评论✍收藏⭐ 引言: 大家好,我是坊钰,为了让大家深入了解C语言,我开创了【玩转C语言系列】,将为大家介绍C语言相关知识…...
![](https://i-blog.csdnimg.cn/direct/393075999f9349978ec688a30a1e9b93.png)
Apache Flink 任务提交模式
Flink 任务提交模式 Flink可以基于多种模式部署:基于Standalone 部署模式,基于Yarn部署模式,基于Kubernetes部署模式以上不同集群部署模式下提交Flink任务会涉及申请资源,各角色交互过程,不同模式申请资源涉及到的角色…...
![](https://i-blog.csdnimg.cn/direct/aa12e5c50764435db81a8fdca4c27876.png)
Ubuntu22.04安装OMNeT++
一、官网地址及安装指南 官网地址:OMNeT Discrete Event Simulator 官网安装指南(V6.0.3):https://doc.omnetpp.org/omnetpp/InstallGuide.pdf 官网下载地址:OMNeT Downloads 旧版本下载地址:OMNeT Old…...
![](https://www.ngui.cc/images/no-images.jpg)
Matlab课程设计——手指静脉识别项目
手指静脉识别项目 项目方案设计介绍 本项目实现手指图像的处理和匹配算法,需要处理的数据是本人不同手指的图像,首先经过图像处理,使得指静脉的纹理增强凸显处理,然后将所有的这些图像进行相互间的匹配,检验类内和类…...
![](https://www.ngui.cc/images/no-images.jpg)
centos软件安装
安装方式 一、二进制安装 --解压即用,只针对特殊平台 --jdk tomcat 二、RPM:按照一定规范安装软件,无法安装依赖的文件 --mysql 三、yum:远程安装基于RPM,把依赖的文件安装上去,需要联网 四、源码安装 jdk安…...
![](https://s1.51cto.com/attachment/201309/005924444.jpg)
网站推广外链/win10系统优化软件哪个好
部署LNMP和部署LAMP方法是一样的,只不过是WEB服务器软件换了而已,这里使用的WEB服务器软件就是一篇文章中所部署的Nginx,所谓的LNMP也就是LinuxNginxMysqlPHP。之所以使用LNMP是因为它是一个高性能的动态网站平台,在某些领域比LAM…...
![](https://img-blog.csdnimg.cn/img_convert/5ec46349935c6fb71005867e767ed0a5.png)
wordpress拼音/百度竞价推广效果好吗
C语言之类型转换 类型之间的转换 1.c语言中的数据类型可以进行转换 —强制类型转换 —隐式类型转换 //示例1 int main() {long l 800;int i (int)l; //强制类型转换return 0; }//示例2 int main() {short s 800;int i s; //隐式类型转换//no error,no warningreturn …...
![](/images/no-images.jpg)
三级分销网站开发/qq空间秒赞秒评网站推广
主要是大小写问题 在扁平发布模式下,如果存在大小写不同的文件,文件会被替换掉。而模拟上运行没问题,在真机上运行 有问题。找了半天才发现,坑啊!转载于:https://www.cnblogs.com/xdao/p/cocos2dx_keng03.html...
![](https://img-blog.csdnimg.cn/img_convert/8b858649e658d2c2aba40d10028fa673.png)
高端网站建设与管理/网络营销师证书含金量
小吴同学,能不能更新快一点!!!感谢各位还未取消关注,确实是工作忙的慌,只有晚上可以总结写点东西,还望大家继续支持。今天分享的是关于720全景图制作的方法,现在市场上其实有很多设备…...
怎么在网站上做签到/郑州seo多少钱
电脑一直都很擅长视觉识别。有时它们识别一系列图像中某个个体的能力能够与人类相媲美。但相似的结果是否说明了电脑能够模拟人类的视觉系统呢?回答这个问题或许可能会发现电脑系统比不上人类的地方。 《美国科学院院刊》发表了一篇论文提到了电脑和人类视觉系统的不…...
![](/images/no-images.jpg)
白银网站建设白银/线下营销方式主要有哪些
当FCoE应用于存储网络时,它的采用速度并没有想象中那么快。但是,用户最终克服了当时的障碍,使得FCoE被广泛采用。 是否该考虑在存储网络中使用以太网光纤通道(FCoE)? James Damoulakis:几年前,当FCoE应用于存储网络时…...