LeetCode 栈和队列OJ题目分享

目录

  • 有效的括号(括号匹配)
  • 用栈实现队列
  • 用队列实现栈
  • 设计循环队列

有效的括号(括号匹配)

链接: link
题目描述:
在这里插入图片描述
题目思路:

1、如果是左括号“( { [ ”就入栈

2、如果是右括号“) } ] ”,就取出栈顶元素与该右括号进行匹配
如果不匹配,就直接return false
如果匹配,s++,指针继续向下走,寻找下一个括号,进行上述操作

注意:
1、如果只有左括号,则栈不为空,则要return false
2、如果只有右括号,栈为空,不能取栈顶元素进行匹配
3、内存泄漏问题,每次返回一个bool值之前都要销毁栈,以免发生内存泄漏
代码实现:

typedef char STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

void STInit(ST* pst);
void STDestroy(ST* pst);
void STPush(ST* pst, STDataType x);
void STPop(ST* pst);
STDataType STTop(ST* pst);
bool STEmpty(ST* pst);
int STSize(ST* pst);
void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;//最开始不malloc空间
	//pst->top = -1;//指向栈顶元素
	pst->top = 0;//指向栈顶元素的下一个位置,表示已经有元素
	pst->capacity = 0;
}
void STDestroy(ST* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->top = 0;
	pst->capacity = 0;
}
void STPush(ST* pst, STDataType x)
{
	assert(pst);
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}
void STPop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	pst->top--;
}
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	return pst->a[pst->top - 1];//栈顶元素
}
bool STEmpty(ST* pst)
{
	return pst->top == 0;
}
int STSize(ST* pst)
{
	assert(pst);
	return pst->top;
}

bool isValid(char * s)
{
    ST st;
    STInit(&st);
    while(*s)
    {
         //1、左括号入栈
        if(*s=='('
        || *s=='{'
        || *s=='[')
        {
            STPush(&st,*s);
        }
        //2、右括号出栈匹配
        else
        {
            //不匹配情况

            //如果栈空,只有右括号,则不匹配,直接返回false
            if(STEmpty(&st))
            {
                return false;
            }
            char top = STTop(&st);
            STPop(&st);
            if((*s==']'&&top!='[')
            || (*s=='}'&&top!='{')
            ||(*s==')'&&top!='('))
            {
                return false;
            }
            //匹配
        }
        s++;//向后遍历字符串寻找括号
    }
    bool ret = STEmpty(&st);//如果栈空返回true,否则返回false
    STDestroy(&st);
    return ret;
}

用栈实现队列

链接: link
题目描述:
在这里插入图片描述
在这里插入图片描述
题目思路:

两个栈实现队列,首先明确:
栈后进先出
队列先进先出

![在这里插入图片描述](https://img-blog.csdnimg.cn/a031ca50ab964ca6bd8b008f47c65dbf.png方法:
方法:
在这里插入图片描述

此处方法就是先倒数据,将栈1的元素4 3 2全部导入栈2中,最后删除1,如下图

在这里插入图片描述

在这个过程中,将栈1的全部元素导入栈2后,我们可以发现栈2出栈的顺序就是队列出队的顺序,于是可以将两个栈做如下更改:

在这里插入图片描述
分析:

1、队列的结构

typedef struct 
{
    ST pushst;
    ST popst;
} MyQueue;
MyQueue* myQueueCreate() 
{
    MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
    if(obj==NULL)
    {
        perror("malloc fail");
        return NULL;
    }
    STInit(&obj->pushst);
    STInit(&obj->popst);
    return obj;
}

2、入队操作
在这里插入图片描述

此处入队操作就是入栈操作,将元素入到pushst栈当中

void myQueuePush(MyQueue* obj, int x) 
{
    STPush(&obj->pushst,x);
}

3、返回队列开头元素在这里插入图片描述

首先判断popst中是否为空,如果popst为空,判断pushst是否为空,如果pushst不为空,将pushst中的元素入栈到popst中,最后返回popst的栈顶元素

int myQueuePeek(MyQueue* obj) //只取栈顶元素
{
    if(STEmpty(&obj->popst))
    {
        while(!STEmpty(&obj->pushst))
        {
            STPush(&obj->popst,STTop(&obj->pushst));
            STPop(&obj->pushst);
        }
    }
    return STTop(&obj->popst);//popst中的栈顶元素,即pushst中的栈底元素
}

4、移除队列开头的元素,并返回队头元素
在这里插入图片描述

复用myQueuePeek函数,保存该函数的返回值,再出popst的栈顶元素

int myQueuePop(MyQueue* obj) //删数据 
{
    int front = myQueuePeek(obj);
    STPop(&obj->popst);
    return front;
}

5、判空
在这里插入图片描述

popst和pushst同时为空

bool myQueueEmpty(MyQueue* obj) 
{
    return STEmpty(&obj->pushst)&&STEmpty(&obj->popst);
}

6、销毁

void myQueueFree(MyQueue* obj) 
{
    STDestroy(&obj->pushst);
    STDestroy(&obj->popst);
     free(obj);
}

整体代码:

typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

void STInit(ST* pst);
void STDestroy(ST* pst);
void STPush(ST* pst, STDataType x);
void STPop(ST* pst);
STDataType STTop(ST* pst);
bool STEmpty(ST* pst);
int STSize(ST* pst);

void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;//最开始不malloc空间
	//pst->top = -1;//指向栈顶元素
	pst->top = 0;//指向栈顶元素的下一个位置,表示已经有元素
	pst->capacity = 0;
}
void STDestroy(ST* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->top = 0;
	pst->capacity = 0;
}
void STPush(ST* pst, STDataType x)
{
	assert(pst);
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}
void STPop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	pst->top--;
}
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	return pst->a[pst->top - 1];//栈顶元素
}
bool STEmpty(ST* pst)
{
	return pst->top == 0;
}
int STSize(ST* pst)
{
	assert(pst);
	return pst->top;
}
typedef struct 
{
    ST pushst;
    ST popst;
} MyQueue;
MyQueue* myQueueCreate() 
{
    MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
    if(obj==NULL)
    {
        perror("malloc fail");
        return NULL;
    }
    STInit(&obj->pushst);
    STInit(&obj->popst);
    return obj;
}


void myQueuePush(MyQueue* obj, int x) 
{
    STPush(&obj->pushst,x);
}

int myQueuePop(MyQueue* obj) //删数据 
{
    int front = myQueuePeek(obj);
    STPop(&obj->popst);
    return front;
}

int myQueuePeek(MyQueue* obj) //只取栈顶元素
{
    if(STEmpty(&obj->popst))
    {
        while(!STEmpty(&obj->pushst))
        {
            STPush(&obj->popst,STTop(&obj->pushst));
            STPop(&obj->pushst);
        }
    }
    return STTop(&obj->popst);//popst中的栈顶元素,即pushst中的栈底元素
}

bool myQueueEmpty(MyQueue* obj) 
{
    return STEmpty(&obj->pushst)&&STEmpty(&obj->popst);
}

void myQueueFree(MyQueue* obj) 
{
    STDestroy(&obj->pushst);
    STDestroy(&obj->popst);
     free(obj);
}

用队列实现栈

链接: link
题目描述:
在这里插入图片描述
在这里插入图片描述
题目思路:

题目中给我们两个队列实现一个栈,首先明确:
1、队列的性质:先进先出
2、栈的性质:后进先出

在这里插入图片描述

如何才能使用两个队列实现栈的后进先出?
本题给的两个队列就是用来导数据,进而实现栈的后进先出的性质

举例:如上图,如果说我们要出数据5,那么就需要将队列1当中的1 2 3 4 先入到队列2中,再出数据5,这样就实现了后进先出的性质。
在这里插入图片描述
注意:
如何入数据?
1、如果两个队列中的一个队列为空一个队列不为空,那么数据入到非空队列中
2、如果两个队列都为空,数据入到其中一个队列
分析:
1、栈的结构和栈的创建
在这里插入图片描述

方法1:给定MyStack栈中的两个队列都是结构体类型,直接malloc动态开辟一个栈的空间,里面存放队列1 q1和队列2 q2
初始化队列使用结构体指针。

在这里插入图片描述

方法2:给定MyStack栈中的两个队列都是结构体指针类型,动态开辟栈的空间,再动态开辟队列的空间,这样在初始化时就不需要进行取地址操作,因为q1和q2就是结构体指针类型。

在这里插入图片描述
2、入数据操作
在这里插入图片描述

1、如果q1不为空,那么就入队列1中
2、如果q2不为空,那么就入队列2中
3、如果两个都不为空,则随意入队列

void myStackPush(MyStack* obj, int x) 
{
    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1,x);
    }
    else
    {
        QueuePush(&obj->q2,x);
    }
}

3、出栈操作——倒数据

1、将非空队列的队头的数据导入空队列当中——入队
2、弹出非空队列的队头数据
3、取栈顶元素

int myStackPop(MyStack* obj) 
{
    Queue* qEmpty=&obj->q1;
    Queue* qNoneEmpty = &obj->q2;
    if(!QueueEmpty(&obj->q1))
    {
        Queue* qEmpty=&obj->q2;
        Queue* qNoneEmpty = &obj->q1;
    }
    while(QueueSize(qNoneEmpty)>1)
    {
        QueuePush(qEmpty,QueueFront(qNoneEmpty));
        QueuePop(qNoneEmpty);
    }
    int top = QueueFront(qNoneEmpty);
    QueuePop(qNoneEmpty);
    return top;
}

4、取栈顶元素——队尾元素

1、第一个队列不为空,就取队尾元素
2、反之取第二个队列的队尾元素

int myStackTop(MyStack* obj) 
{
    if(!QueueEmpty(&obj->q1))
    {
        return QueueBack(&obj->q1);
    }
    else
    {
        return QueueBack(&obj->q2);
    }
}

5、判空

bool myStackEmpty(MyStack* obj) 
{
    return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
}

6、销毁

不仅释放栈,也要释放队列

void myStackFree(MyStack* obj) 
{
    QueueDestroy(&obj->q1);
    QueueDestroy(&obj->q2);
    free(obj);
}

整体代码:

typedef int QDataType;
//每个节点的结构

typedef struct QueueNode
{
	QDataType data;
	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);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);

void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;
	
	//队列为空
	if (pq->ptail == NULL)
	{
		assert(pq->phead == NULL);
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		//队列不空
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}
void QueuePop(Queue* pq)
{
	//类似头删
	assert(pq);
	assert(!QueueEmpty(pq));
	//1、一个节点
	//2、多个节点
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else
	{
		//头删
		QNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}
	pq->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;
}
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	//return pq->size == 0;
	return pq->phead == NULL && pq->ptail == NULL;
}

typedef struct
{
    Queue q1;//队列1
    Queue q2;//队列2
} MyStack;


MyStack* myStackCreate()
{
    MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
    if (obj == NULL)
    {
        perror("malloc fail");
        return NULL;
    }
    QueueInit(&obj->q1);
    QueueInit(&obj->q2);
    return obj;
}

void myStackPush(MyStack* obj, int x) 
{
    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1,x);
    }
    else
    {
        QueuePush(&obj->q2,x);
    }
}

int myStackPop(MyStack* obj) 
{
    Queue* qEmpty=&obj->q1;
    Queue* qNoneEmpty = &obj->q2;
    if(!QueueEmpty(&obj->q1))
    {
       qEmpty=&obj->q2;
       qNoneEmpty = &obj->q1;
    }
    while(QueueSize(qNoneEmpty)>1)
    {
        QueuePush(qEmpty,QueueFront(qNoneEmpty));
        QueuePop(qNoneEmpty);
    }
    int top = QueueFront(qNoneEmpty);
    QueuePop(qNoneEmpty);
    return top;
}

int myStackTop(MyStack* obj) 
{
    if(!QueueEmpty(&obj->q1))
    {
        return QueueBack(&obj->q1);
    }
    else
    {
        return QueueBack(&obj->q2);
    }
}

bool myStackEmpty(MyStack* obj) 
{
    return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
}

void myStackFree(MyStack* obj) 
{
    QueueDestroy(&obj->q1);
    QueueDestroy(&obj->q2);
    free(obj);
}

设计循环队列

链接: link
题目描述:
在这里插入图片描述
在这里插入图片描述
思路分析:
在这里插入图片描述

本题使用数组设计循环队列
1、假设循环队列存储k个数据,开k+1个空间,每次入队一个元素,rear指针都会指向该元素的后一个位置。

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

1、循环队列的结构

在这里插入图片描述

typedef struct 
{
    int front;
    int rear;
    int k;//队列中元素个数
    int* a;
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) 
{
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    obj->a = (int*)malloc(sizeof(int*)*(k+1));
    obj->front=obj->rear = 0;
    obj->k=0;
    return obj;
}

2、判断循环队列为空:front=rear
在这里插入图片描述

bool myCircularQueueIsEmpty(MyCircularQueue* obj) 
{
    return obj->rear==obj->front;
}

3、判断队列满:(rear+1)%(k+1)==front
在这里插入图片描述

bool myCircularQueueIsFull(MyCircularQueue* obj) 
{
    return (obj->rear+1)%(obj->k+1)==obj->front;

}

4、入数据

在rear位置入数据再让rear++,特殊情况:循环队列可能会绕回去,所以要判断rear的位置

在这里插入图片描述

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) 
{
    if( myCircularQueueIsEmpty(obj))
    {
        return false;
    }
    obj->a[obj->rear]=value;
    obj->rear++;
    obj->rear%=(obj->k+1);//保证范围
}

5、出数据(删除数据)

判空,如果为空,则不进行删除操作
删除操作即让front++,并且保证front的范围

在这里插入图片描述

bool myCircularQueueDeQueue(MyCircularQueue* obj) 
{
     if( myCircularQueueIsEmpty(obj))
    {
        return false;
    }
    obj->front++;
    obj->front%=(obj->k+1);//保证范围
    return true;
}

6、返回队头和队尾数据
在这里插入图片描述
在这里插入图片描述

int myCircularQueueFront(MyCircularQueue* obj) 
{
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    return obj->a[obj->front];
}

int myCircularQueueRear(MyCircularQueue* obj) 
{
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    else if(obj->rear==0)
    {
        return obj->a[obj->rear+k-1];
    }
    else
    {
        return obj->a[obj->rear-1];
    }
}

整体代码:

typedef struct 
{
    int front;
    int rear;
    int k;//队列中元素个数
    int* a;
} MyCircularQueue;

bool myCircularQueueIsEmpty(MyCircularQueue* obj) 
{
    return obj->rear==obj->front;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) 
{
    return (obj->rear+1)%(obj->k+1)==obj->front;

}
MyCircularQueue* myCircularQueueCreate(int k) 
{
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    obj->a = (int*)malloc(sizeof(int)*(k+1));
    obj->front=obj->rear = 0;
    obj->k=k;
    return obj;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) 
{
    if( myCircularQueueIsFull(obj))
    {
        return false;
    }
    obj->a[obj->rear]=value;
    obj->rear++;
    obj->rear%=(obj->k+1);//保证范围
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) 
{
     if( myCircularQueueIsEmpty(obj))
    {
        return false;
    }
    obj->front++;
    obj->front%=(obj->k+1);//保证范围
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) 
{
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    return obj->a[obj->front];
}

int myCircularQueueRear(MyCircularQueue* obj) 
{
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
   return obj->a[(obj->rear+obj->k)%(obj->k+1)];
}



void myCircularQueueFree(MyCircularQueue* obj) 
{
    free(obj->a);
    free(obj);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

程序员:面试造火箭,入职拧螺丝?太难了···

刚开始工作的时候,我也想不通这个问题,甚至很鄙视这种现象。后面当了面试官,做到了公司中层管理,也会站在公司以及行业角度去重新思考这个问题。 为什么这种现象会越来越普遍呢?尤其在 IT 行业愈加明显。 面试看的是…

Packet Tracer – VLAN 实施故障排除场景 2

Packet Tracer – VLAN 实施故障排除场景 2 拓扑图 地址分配表 设备 接口 IPv4 地址 子网掩码 默认网关 S1 VLAN 56 192.168.56.11 255.255.255.0 不适用 S2 VLAN 56 192.168.56.12 255.255.255.0 不适用 S3 VLAN 56 192.168.56.13 255.255.255.0 不适用 P…

头歌计算机组成原理实验—运算器设计(11)第11关:MIPS运算器设计

第11关:MIPS运算器设计 实验目的 学生理解算术逻辑运算单元(ALU)的基本构成,掌握 Logisim 中各种运算组件的使用方法,熟悉多路选择器的使用,能利用前述实验完成的32位加法器、 Logisim 中的运算组件构造指…

图神经网络:(处理点云)PointNet++的实现

文章说明: 1)参考资料:PYG官方文档。超链。 2)博主水平不高,如有错误还望批评指正。 3)我在百度网盘上传了这篇文章的jupyter notebook和有关文献。超链。提取码8848。 文章目录 简单前置工作学习文献阅读PointNet的实现模型问题 简单前置工作…

智慧井盖监测终端,智能井盖-以科技解决智慧城市“顽疾”,守护城市生命线

平升电子智慧井盖监测终端,智能井盖-以科技解决智慧城市“顽疾”,守护城市生命线-智慧井盖,实现对井下设备和井盖状态的监测及预警,是各类智慧管网管理系统中不可或缺的重要设备,解决了井下监测环境潮湿易水淹、电力供应困难、通讯不畅等难题…

XDP入门--BPF程序如何转发报文到其它网卡

本文目录 1、测试环境:2、实现的功能,使用bpf_redirect直接转发收到的报文到另外一张网卡3、测试步骤与测试结果 1、测试环境: 参照把树莓派改造成无线网卡(3)-----共享无线网络,无线网络转换成有线网络,让有线网络设…

插入排序、选择排序、冒泡排序小结(45)

小朋友们好,大朋友们好! 我是猫妹,一名爱上Python编程的小学生。 和猫妹学Python,一起趣味学编程。 今日主题 插入排序、选择排序、冒泡排序有什么区别? 原理不同 插入排序是将未排序的元素逐个插入到已排序序列中…

Unity之ASE从入门到精通 目录

前言 Amplify Shader Editor (ASE) 是受行业领先软件启发的基于节点着色器创建工具。它是一个开放且紧密集成的解决方案,提供了熟悉和连贯的开发环境,使 Unity 的 UI 约定和着色器的使用无缝地融合一起 目录 这里是ASE从入门到精通专栏的目录,不停更新中,有问题随时留…

入门JavaScript编程:上手实践四个常见操作和一个轮播图案例

部分数据来源:ChatGPT 简介 JavaScript是一门广泛应用于Web开发的脚本语言,它主要用于实现动态效果和客户端交互。下面我们将介绍几个例子,涵盖了JavaScript中一些常见的操作,包括:字符串、数组、对象、事件等。 例子…

rk3568 适配rk809音频

rk3568 适配rk809音频 RK809是一款集成了多种功能的电源管理芯片,主要用于笔记本电脑、平板电脑、工控机等设备的电源管理。以下是RK809的详细功能介绍: 电源管理:控制电源的开关、电压、电流等参数,保证设备的稳定运行。音频管…

Unity之使用Photon PUN开发多人游戏教程

前言 Photon是一个网络引擎和多人游戏平台,可以处理其服务器上的所有请求,我们可以在 Unity(或其他游戏引擎)中使用它,并快速把游戏接入Photon的网络中,而我们就可以专注于在项目中添加逻辑,专注于游戏玩法和功能了。 PUN(Photon Unity Networking)是一种开箱即用的解…

什么是DevOps?如何理解DevOps思想?

博文参考总结自:https://www.kuangstudy.com/course/play/1573900157572333569 仅供学习使用,若侵权,请联系我删除! 1、什么是DevOps? DevOps是一种思想或方法论,它涵盖开发、测试、运维的整个过程。DevOps强调软件开…

Maven方式构建Spring Boot项目

文章目录 一,创建Maven项目二,添加依赖三,创建入口类四,创建控制器五,运行入口类六,访问Web页面七,修改访问映射路径八,定制启动标语1、创建标语文件2、生成标语字符串3、编辑标语文…

DNDC模型在土地利用变化、未来气候变化下的建模方法及温室气体时空动态模拟实践技术

DNDC模型讲解 1.1 碳循环模型简介 1.2 DNDC模型原理 1.3 DNDC下载与安装 1.4 DNDC注意事项 ​ DNDC初步操作 2.1 DNDC界面介绍 2.2 DNDC数据及格式 2.3 DNDC点尺度模拟 2.4 DNDC区域尺度模拟 2.5 DNDC结果分析 ​ DNDC气象数据制备 3.1 数据制备中的遥感和GIS技术 3…

Vue3 + TypeScript + Uniapp 开发小程序【医疗小程序完整案例·一篇文章精通系列】

当今的移动应用市场已经成为了一个日趋竞争激烈的领域,而开发一个既能在多个平台上运行,又能够高效、可维护的应用则成为了一个急需解决的问题。 在这个领域中,Vue3 TypeScript Uniapp 的组合已经成为了一种受欢迎的选择,特别…

ODB 2.4.0 使用延迟指针 lazy_shared_ptr 时遇到的问题

最近在学习使用C下的ORM库——ODB,来抽象对数据库的CURD,由于C的ORM实在是太冷门了,ODB除了官方英语文档,几乎找不到其他好用的资料,所以在使用过程中也是遇到很多疑惑,也解决很多问题。近期遇到的一个源码…

推荐系统系列之推荐系统概览(下)

在推荐系统概览的第一讲中,我们介绍了推荐系统的常见概念,常用的评价指标以及首页推荐场景的通用召回策略。本文我们将继续介绍推荐系统概览的其余内容,包括详情页推荐场景中的通用召回策略,排序阶段常用的排序模型,推…

Keil Debug 逻辑分析仪使用

Keil Debug 逻辑分析仪使用 基础配置 更改对应的bebug窗口参数 两边的 Dialog DLL 更改为:DARMSTM.DLL两边的 Parameter (这里的根据单片机型号更改)更改为:-pSTM32F103VE 选择左边的 Use Simulator 选项。 打开Debug和其中的逻…

数据全生命周期管理

数据存储 时代"海纳百川,有容乃大"意味结构化、半结构和非结构化多样化的海量的 ,也意味着批数据和流数据多种数据形式的存储和计算。面对不同数据结构、数据形式、时效性与性能要求和存储与计算成本等因素考虑,应该使用适合的存储…

iptables防火墙(二)

iptables防火墙(二) 一、SNAT策略1、SNAT策略简述2、配置实验 二、DNAT策略1、DNAT策略简述2、配置实验 三、Linux抓包工具tcpdump四、防火墙规则保存 一、SNAT策略 1、SNAT策略简述 SNAT策略就是将从内网传给外网的数据包的源IP由私网IP转换成公网IP&…