数据结构——队列和栈的面试题分析

news2025/1/20 2:49:37

之前我们写过了有效括号的分析了,接下来,我们继续来学习一下,有关栈和队列之间的相关转换的题目吧。

栈实现队列

232. 用栈实现队列 - 力扣(LeetCode)

这里我们使用c语言的形式来写,所以我们先自己模拟一个栈。 

typedef int  STDataType;

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

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

void STInit(ST* ps)
{
	assert(ps);

	ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
	if (ps->a == NULL)
	{
		perror("malloc fail");
		return;
	}

	ps->capacity = 4;
	ps->top = 0;   // top是栈顶元素的下一个位置

	//ps->top = -1;   // top是栈顶元素位置
}

void STDestroy(ST* ps)
{
	assert(ps);

	free(ps->a);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}

void STPush(ST* ps, STDataType x)
{
	assert(ps);

	if (ps->top == ps->capacity)
	{
		STDataType* tmp = (STDataType*)realloc(ps->a,
			sizeof(STDataType) * ps->capacity*2);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}

		ps->a = tmp;
		ps->capacity *= 2;
	}

	ps->a[ps->top] = x;
	ps->top++;
}

void STPop(ST* ps)
{
	assert(ps);
   // assert(!STEmpty(ps));

	ps->top--;
}

int STSize(ST* ps)
{
	assert(ps);

	return ps->top;
}

bool STEmpty(ST* ps)
{
	assert(ps);

	return ps->top == 0;
}

STDataType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));

	return ps->a[ps->top - 1];
}

上面代码是我们之前写过的栈那篇文章的内容,如果有兴趣可以自行去了解了解鸭。

这里我们就之间来使用它就行了。 

接下来我们先来讲解一下它的思路吧:

1.我们已经明白了,栈是后进先出的,队列是先进先出的。

2.那么,要使用两个栈来实现队列。下图分析:

1)push那边基本没有太大的问题,直接一个一个push到其中一个栈就行。

2)Pop那边,我们该怎么实现呢?

我们下图可以看出:

如果单单是上面的话,你直接pop,那么会发现,它会先删除4这个数字,而队列的话,它得先删1这个数字,这显然不对。所以我们得换种方法。

你看如果是这样的话:

接着,你会发现,第二个栈是不是就可以直接删去也可以达到队列的效果了。

因此我们可以有这种思路:

建立两个栈,分别是专门push和pop的栈 

如果你想要插入的话,直接在push那边插就可以了,那么什么时候移动过去push的数据到pop那边呢?就当检查到pop那边的数据为空时,再把push那边的数据移动过pop即可。 

好了,有了下面的铺垫后,我们开始这道题的代码。

一:建立两个栈

typedef struct {
  ST Pushst;
  ST Popst;  
} MyQueue;

此外,为了更直观地看,可以画出图片来辅助理解:

 创建MyQueue部分

MyQueue* myQueueCreate() {
  MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));  
  if(obj==NULL)
  {
    perror("malloc fail");

  }  
  初始化
  STInit(&obj->Pushst);
  STInit(&obj->Popst);
  记得最后返回obj
  return obj;
}

push部分 

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

}

 返回头数据

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);
}

解释:

1.如果pop那边为空时,条件为真,进入循环。开始倒数据,(这里也就是上面我解释过的思路那里)

2.最后返回栈顶元素即可完成了。 

删除部分

int myQueuePop(MyQueue* obj) {
    int Front=myQueuePeek(obj);
    STPop(&obj->Popst);
    return Front;
}


判断空部分 

bool myQueueEmpty(MyQueue* obj) {
    return STEmpty(&obj->Pushst) &&STEmpty(&obj->Popst);
}

  这里直接用我们写的模拟栈的判断空函数部分就行了

销毁部分

void myQueueFree(MyQueue* obj) {
    STDestroy(&obj->Pushst);
    STDestroy(&obj->Popst);
    free(obj);
}

需要注意的是,我们这里不可以直接是否push栈,和pop栈,

但是呢我们有Destory神器,我们直接调用它就可以了。

 这道题的最后,我们附上总代码:

typedef int  STDataType;

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

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

void STInit(ST* ps)
{
	assert(ps);

	ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
	if (ps->a == NULL)
	{
		perror("malloc fail");
		return;
	}

	ps->capacity = 4;
	ps->top = 0;   // top是栈顶元素的下一个位置

	//ps->top = -1;   // top是栈顶元素位置
}

void STDestroy(ST* ps)
{
	assert(ps);

	free(ps->a);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}

void STPush(ST* ps, STDataType x)
{
	assert(ps);

	if (ps->top == ps->capacity)
	{
		STDataType* tmp = (STDataType*)realloc(ps->a,
			sizeof(STDataType) * ps->capacity*2);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}

		ps->a = tmp;
		ps->capacity *= 2;
	}

	ps->a[ps->top] = x;
	ps->top++;
}

void STPop(ST* ps)
{
	assert(ps);
   // assert(!STEmpty(ps));

	ps->top--;
}

int STSize(ST* ps)
{
	assert(ps);

	return ps->top;
}

bool STEmpty(ST* ps)
{
	assert(ps);

	return ps->top == 0;
}

STDataType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));

	return ps->a[ps->top - 1];
}

typedef struct {
  ST Pushst;
  ST Popst;  
} MyQueue;


MyQueue* myQueueCreate() {
  MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));  
  if(obj==NULL)
  {
    perror("malloc fail");

  }  
  STInit(&obj->Pushst);
  STInit(&obj->Popst);
  return obj;
}

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

}

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);
}

int myQueuePop(MyQueue* obj) {
    int Front=myQueuePeek(obj);
    STPop(&obj->Popst);
    return Front;
}


bool myQueueEmpty(MyQueue* obj) {
    return STEmpty(&obj->Pushst) &&STEmpty(&obj->Popst);
}

void myQueueFree(MyQueue* obj) {
    STDestroy(&obj->Pushst);
    STDestroy(&obj->Popst);
    free(obj);
}

队列实现栈 

225. 用队列实现栈 - 力扣(LeetCode)

1.同样,我们想到:队列是先进先出,栈是后进先出。

2.这里我们使用的方法是 :

1)保持一个队列为空,一个队列存数据。

2)出栈,前面的数据倒入空队列。

好了,至此,我们开始解这道题:

 1.模拟一个队列

#include<stdio.h>
#include<assert.h>
#include<stdbool.h>
#include<stdlib.h>
typedef char QDatatype;
typedef struct Queuenode
{
	struct Queuenode* next;
	QDatatype data;
}QNode;

typedef struct Queue
{
	QNode* head;
	QNode* tail;
	int size;
}Queue;

void QInit(Queue* pq);
void QDestory(Queue* pq);
void QueuePush(Queue* pq,QDatatype x);
void QueuePop(Queue* pq);
int Size(Queue* pq);
bool QEmpty(Queue* pq);
QDatatype QueueFront(Queue* pq);
QDatatype QueueBack(Queue* pq);
void QInit(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
	pq->size = 0;
}
void QDestory(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;
	pq->size = 0;
}
void QueuePush(Queue* pq, QDatatype x)
{
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;
	if (pq->head == NULL)
	{
		assert(pq->tail == NULL);
		pq->head = pq->tail = newnode;

	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
	pq->size++;

}
void QueuePop(Queue* pq)
{
	assert(pq);
	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		
		QNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;
	}
	pq->size--;
}

int Size(Queue* pq)
{
	assert(pq);
	return pq->size;
}
bool QEmpty(Queue* pq)
{
	assert(pq);
	return pq->size==0;
}

QDatatype QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QEmpty(pq));
	return pq->head->data;
}
QDatatype QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QEmpty(pq));
	return pq->tail->data;
}

这个也是之前写过的文章有队列模拟实现的分析,有兴趣的可以去看看.

2.搭建两个队列 

typedef struct {
    Queue q1;
    Queue q2;
} MyStack;

这里呢,可以画个图来方便理解

创建MyTack部分

MyStack* myStackCreate() {
    MyStack* pst=(MyStack*)malloc(sizeof(MyStack));
    if(pst==NULL)
    {
        perror("malloc fail");
        return NULL;
    }
    QInit(&pst->q1);
    QInit(&pst->q2);
    最后记得返回
    return pst;
}

 这里跟上面一题的这个部差不多。

push部分

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

插入部分,是看那个不为空,就往哪个队列插。

3.删除部分:

int myStackPop(MyStack* obj) {
    Queue* empty=&obj->q1;
    Queue* nonempty=&obj->q2;
    if(!QEmpty(&obj->q1))   
    {
        empty=&obj->q2;
        nonempty=&obj->q1;
    }
    //倒数据
    while(Size(nonempty)>1)
    {
        QueuePush(empty,QueueFront(nonempty));
        QueuePop(nonempty);
    }
    int top=QueueFront(nonempty);
    QueuePop(nonempty);
   return top;
}

1.这里先定义两个队列的指针,一个叫空的队列,一个叫不为空的队列。(方便辨别)

由于不能保证它q1q2哪个为空,所以加一个if语句,如果不对就换过来。

2.倒数据:将原本不为空的队列的数据移动到空的,只留下最后一个数据,然后再删去。

3.最后返回头队列的数据

4.栈顶元素

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

这里的栈顶元素,也就是队列的尾,直接返回队列的尾巴就行了。

 5.判断空部分

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

 6.释放部分

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

这道题,基本就结束了,这里附上总代码:

typedef char QDatatype;
typedef struct Queuenode
{
	struct Queuenode* next;
	QDatatype data;
}QNode;

typedef struct Queue
{
	QNode* head;
	QNode* tail;
	int size;
}Queue;

void QInit(Queue* pq);
void QDestory(Queue* pq);
void QueuePush(Queue* pq,QDatatype x);
void QueuePop(Queue* pq);
int Size(Queue* pq);
bool QEmpty(Queue* pq);
QDatatype QueueFront(Queue* pq);
QDatatype QueueBack(Queue* pq);
void QInit(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
	pq->size = 0;
}
void QDestory(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;
	pq->size = 0;
}
void QueuePush(Queue* pq, QDatatype x)
{
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;
	if (pq->head == NULL)
	{
		assert(pq->tail == NULL);
		pq->head = pq->tail = newnode;

	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
	pq->size++;

}
void QueuePop(Queue* pq)
{
	assert(pq);
	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		
		QNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;
	}
	pq->size--;
}

int Size(Queue* pq)
{
	assert(pq);
	return pq->size;
}
bool QEmpty(Queue* pq)
{
	assert(pq);
	return pq->size==0;
}

QDatatype QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QEmpty(pq));
	return pq->head->data;
}
QDatatype QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QEmpty(pq));
	return pq->tail->data;
}
typedef struct {
    Queue q1;
    Queue q2;
} MyStack;


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

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

int myStackPop(MyStack* obj) {
    Queue* empty=&obj->q1;
    Queue* nonempty=&obj->q2;
    if(!QEmpty(&obj->q1))
    {
        empty=&obj->q2;
        nonempty=&obj->q1;
    }
    //倒数据
    while(Size(nonempty)>1)
    {
        QueuePush(empty,QueueFront(nonempty));
        QueuePop(nonempty);
    }
    int top=QueueFront(nonempty);
    QueuePop(nonempty);
   return top;
}

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

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

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

设置循环队列 

622. 设计循环队列 - 力扣(LeetCode)

 注意:这里不是你要插入一个数据才开这个节点,而是最开始就要把这个链表开好。

开始的时候为空,那你是不是要一个一个插数据进去才能满啊,这个队列。

 

但是,当你填满之后,你会发现这里会出现一个问题:

front和rear重合了。这和刚刚开始空的时候一致啊,我们无法区分满和空这两种情况啊:

那么我们有什么方式解决呢?

这里我们有两种方式解决:

 1.加size:循环的时候,增加一个size可以判断空满的问题size=0就是空,size=k就是满了

2.多一个位置(不是哨兵位):出队列:移动front就可以了

用数组:加size
删到某一个的时候,在想要去push的话,就可以size++,或者取模的形式,就可以回去


满的时候:就是rear+1=front

 

同样,满的时候不能插入(即判断rear-> next !=front),此时它不会插入了。

空的时候:就是rear的下一个是front就是了

这是推荐使用数组的形式,因为链表的唯一优势就是把尾的时候,直接next就可以了


找那个的话,这里不能--,只能-1,不然它就变了


记住你malloc几次就要free几次,不要忘记了。

好了,现在正式开始我们这道题解:

这里主要使用数组来解这道题:

建立结构体

typedef struct {
    数组
    int *a;
    头
    int front;
    尾
    int rear;
    长度
    int k;
} MyCircularQueue;

create部分

MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    if(obj==NULL)
    {
        perror("malloc fail");
        
    }
    obj->front=obj->rear=0;
    多开一个空间
    obj->a=(int*)malloc(sizeof(int)*(k+1));
    obj->k=k;
    return obj;
}

1.首先是先创建好数组 

2.再初始化,把front和rear置空

3.记录长度k。

4.最后记得返回obj

判断满

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

解释:(obj->rear+1)%(obj->k+1)==obj->front;这是为了防止数组越界,%(k+1)把下标都控制在k之内。-------》就像4%7==4,%一个比它大的数,永远都在这个范围之内。

判断空

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

上面有解释了。

插入数据

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

1.这里需要主要的是如果这个队列已经满了的话,它就不能插了,就返回错误就行了。

2.把数据插入到rear后,再++移动rear

3.这里同样要注意数组越界的情况。

4.这里入队列就是rear++,倒入数据,

删数据 

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
   if(myCircularQueueIsEmpty(obj))
    return false;

    ++obj->front;
    obj->front %=(obj->k+1);
        return true;
}

1.出队列就是front++,唯一他们有一个点就是麻烦的点就是绕到到最后一个数据的下一个时
k+1一定要挪一下

返回头数据

int myCircularQueueFront(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }

    return obj->a[obj->front];
}

1.这里要注意本身就为空的情况。

返回尾数据

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

1.注意本身队列为空的情况

2.还要防止数组越界。

释放部分

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

最后,附上总代码

typedef struct {
    int *a;
    int front;
    int rear;
    int k;
} MyCircularQueue;


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

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

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

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull(obj))
        return false;
    
    obj->a[obj->rear++]=value;
    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;
    else
    return obj->a[(obj->rear-1+obj->k+1)%(obj->k+1)];
}

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

到了本次鸡汤部分:

自律使人变强大,实现弯道超车吧!

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

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

相关文章

消息队列实战指南:三大MQ 与 Kafka 适用场景全解析

前言&#xff1a;在当今数字化时代&#xff0c;分布式系统和大数据处理变得愈发普遍&#xff0c;消息队列作为其中的关键组件&#xff0c;承担着系统解耦、异步通信、流量削峰等重要职责。ActiveMQ、RabbitMQ、RocketMQ 和 Kafka 作为市场上极具代表性的消息队列产品&#xff0…

Web前端------表单标签

一.表单标签介绍 1.认识表单 表单---类似于日常生活中的申请单 都是去填写一些信息去申请某个功能&#xff0c;例如&#xff1a;账号密码昵称&#xff0c;登陆网站 2.常见标签 常见的标签 <form></form> 表单标签&#xff0c;所有表单信息都包含在这个标签内…

20250118-读取并显示彩色图像以及提取彩色图像的 R、G、B 分量

读取并显示彩色图像以及提取彩色图像的 R、G、B 分量 import cv2 #彩图R、G、B的提取 import torch from PIL import Image from matplotlib import pyplot as plt import numpy as np读取并显示彩色图像的三种方法&#xff1a; img_path "./data/yndx"1.1 使用 …

下定决心不去读研了。。。

大家好&#xff0c;我是苍何。 之前发表过一篇文章&#xff0c;表达了自己读研的困惑和纠结&#xff0c;得到了大家很多的建议&#xff0c;也引起了很多人的共鸣&#xff0c;在留言区分享了自己的故事&#xff0c;看着这些故事&#xff0c;我觉得都够苍何写一部小说了。 可惜苍…

单链表的新建、查找

10.3 头插法新建链表实战 10.3.1 流程图 10.3.1.1 整体的流程图 10.3.1.2 循环的流程图 10.3.2 代码 !!!头指针始终指向头结点&#xff01;&#xff01;&#xff01;头插法&#xff1a;实则就是不断地插元素插在头结点的后面最初要先给头结点的指针域赋值为NULL #include &…

【unity进阶篇】向量插值运算Vector3.Lerp和Vector3.Slerp

考虑到每个人基础可能不一样&#xff0c;且并不是所有人都有同时做2D、3D开发的需求&#xff0c;所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】&#xff1a;主要讲解C#的基础语法&#xff0c;包括变量、数据类型、运算符、…

CSS 的基础知识及应用

前言 CSS&#xff08;层叠样式表&#xff09;是网页设计和开发中不可或缺的一部分。它用于描述网页的视觉表现&#xff0c;使页面不仅实现功能&#xff0c;还能提供吸引人的用户体验。本文将介绍 CSS 的基本概念、语法、选择器及其在提升网页美观性方面的重要性。 什么是 CSS&…

怎么投稿各大媒体网站?如何快速辨别一家媒体是否适合自己?

在做软文营销时&#xff0c;除去在官号和子账号上投稿外&#xff0c;怎么投稿各大媒体网站是困扰中小企业主的一大难题。没有多余账号、运营成本太高&#xff0c;让不少想做全平台推广的朋友止步于此。为了解决这些问题&#xff0c;今天就让小编来分享一下&#xff0c;怎么在各…

dl学习笔记:(4)简单神经网络

&#xff08;1&#xff09;单层正向回归网络 bx1x2z100-0.2110-0.05101-0.051110.1 接下来我们用代码实现这组线性回归数据 import torch x torch.tensor([[1,0,0],[1,1,0],[1,0,1],[1,1,1]], dtype torch.float32) z torch.tensor([-0.2, -0.05, -0.05, 0.1]) w torch.…

01设计模式(D3_设计模式类型 - D3_行为型模式)

目录 一、模版方法模式 1. 基本介绍 2. 应用案例一&#xff1a;豆浆制作问题 需求 代码实现 模板方法模式的钩子方法 3. View的draw&#xff08;Android&#xff09; Android中View的draw方法就是使用了模板方法模式 模板方法模式在 Spring 框架应用的源码分析 知识小…

Android BitmapShader实现狙击瞄具十字交叉线准星,Kotlin

Android BitmapShader实现狙击瞄具十字交叉线准星&#xff0c;Kotlin <?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.…

【QT】: 初识 QWidget 控件 | QWidget 核心属性(API) | qrc 文件

&#x1f525; 目录 1. 控件概述 控件体系的发展阶段 2. QWidget 核心属性 2.1 核心属性概览2.2 用件可用&#xff08;Enabled&#xff09; 2.3 坐标系&#xff08;Geometry&#xff09; **实例 1: 控制按钮的位置**实例 2: 表白 程序 2.4 窗口标题&#xff08;windowTiltle&a…

复健第二天之[MoeCTF 2022]baby_file

打开题目在线环境可以看到&#xff1a; 感觉要用伪协议去求&#xff0c;但是我们并不知道flag的位置&#xff0c;这里我选择用dirsearch去扫一下&#xff1a; 最像的应该就是flag.php了 于是就构建payload&#xff1a; **?filephp://filter/convert.base64-encode/resource…

Spring Boot + Apache POI 实现 Excel 导出:BOM物料清单生成器(支持中文文件名、样式美化、数据合并)

目录 引言 Apache POI操作Excel的实用技巧 1.合并单元格操作 2.设置单元格样式 1. 创建样式对象 2. 设置边框 3. 设置底色 4. 设置对齐方式 5. 设置字体样式 6.设置自动换行 7. 应用样式到单元格 3. 定位和操作指定单元格 4.实现标签-值的形式 5.列宽设置 1. 设…

【Web】2025西湖论剑·中国杭州网络安全安全技能大赛题解(全)

目录 Rank-l Rank-U sqli or not Rank-l username存在报错回显&#xff0c;发现可以打SSTI 本地起一个服务&#xff0c;折半查找fuzz黑名单&#xff0c;不断扔给fenjing去迭代改payload from flask import Flask, request, render_template_stringapp Flask(__name__)app…

索引(MySQL)

1. 没有索引&#xff0c;可能会有什么问题 索引&#xff1a;提高数据库的性能&#xff0c;索引是物美价廉的东西了。不用加内存&#xff0c;不用改程序&#xff0c;不用调sql&#xff0c;只要执行 正确的 create index &#xff0c;查询速度就可能提高成百上千倍。但是天下没有…

C#在Json序列化时将key和value转为对应的中文

在C#中&#xff0c;实体类可以通过System.Text.Json或Newtonsoft.Json库等方式直接序列化为json字符串&#xff0c;key为字段&#xff08;属性&#xff09;名&#xff0c;value为值。 上面的方式虽然实现简单&#xff0c;但是有个缺陷&#xff0c;就是转化后的json给外人展示时…

23- TIME-LLM: TIME SERIES FORECASTING BY REPRO- GRAMMING LARGE LANGUAGE MODELS

解决问题 用LLM来解决时序预测问题&#xff0c;并且能够将时序数据映射&#xff08;reprogramming&#xff09;为NLP token&#xff0c;并且保持backbone的大模型是不变的。解决了时序序列数据用于大模型训练数据稀疏性的问题。 方法 Input Embedding 输入&#xff1a; X …

使用 Java 开发 Android 应用:Kotlin 与 Java 的混合编程

使用 Java 开发 Android 应用&#xff1a;Kotlin 与 Java 的混合编程 在开发 Android 应用程序时&#xff0c;我们通常可以选择使用 Java 或 Kotlin 作为主要的编程语言。然而&#xff0c;有些开发者可能会想要在同一个项目中同时使用这两种语言&#xff0c;这就是所谓的混合编…

左神算法基础提升--4

文章目录 树形dp问题Morris遍历 树形dp问题 求解这个问题需要用到我们在基础班上学到的从节点的左子树和右子树上拿信息的方法。 求最大距离主要分为两种情况&#xff1a;1.当前节点参与最大距离的求解&#xff1b;2.当前节点不参与最大距离的求解&#xff1b; 1.当前节点参与最…