队列的实现和OJ练习

news2024/11/23 13:26:45

目录

概念

队列的实现

利用结构体存放队列结构

为什么单链表不使用这种方法?

初始化队列

小提示:

队尾入队列

队头出队列

获取队头元素

获取队尾元素

获取队列中有效元素个数

检测队列是否为空

销毁队列

最终代码

循环队列 

队列的OJ题

用队列实现栈

用栈实现队列


概念

只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 的特性,进行插入操作的一端称为队尾,进行删除操作的一端称为队头

队列的实现

tip:队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。

利用结构体存放队列结构

        我们之前在实现单链表的时候使用到了二级指针来达到修改头尾结点的效果,这样会增加代码复杂性和理解难度......

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>

//链式结构:表示队列
typedef int QDataType;
typedef struct QueueNode
{
	QDataType val;
	struct QueueNode* next;
}QNode;

//队列的结构(使用结构体避免了二级指针的使用)
typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;        //存放队列大小
}Queue;

        现在我们依然选择用单链表实现队列,但是我们将指向链表的头尾结点的指针信息都存放在一个结构体中,这样就起到了简化参数传递的作用。即在初始化队列时只需分配一个包含头尾节点、队列大小等信息的结构对象,并将其作为参数传递给相关函数。这样就可以直接通过访问该结构对象中的相应成员变量来修改或获取所需信息

为什么单链表不使用这种方法?

        这是因为在单链表中,使用结构体来表示整个单链表可能会带来一些不必要的复杂性,并且没有明显的好处,相比于这种方法使用二级指针会有以下有点:

1. 简化插入和删除操作:由于插入或删除操作需要调整前后两个节点之间的连接关系(而队列不需要考虑在指定位置插入的问题),将头尾结点分别存放在结构体中可能需要更多额外处理步骤才能保持正确连接关系。

2. 节省内存空间:如果每个节点都包含了头尾信息,则会导致额外占用内存空间,并且增加了维护数据一致性所需付出成本。

3. 降低复杂度:通过仅保存对首元素(即头部)进行引用,在大多数情况下足以满足对单链表进行各种操作所需求。这样可以简化代码逻辑并提高代码可读性与可维护性。

初始化队列

//初始化队列
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

实现步骤: 

1、利用断言检测队列指针的有效性

2、有效则将队列初始化为空队列,即将指向队头元素和队尾元素的指针及队列元素个数都置为空

小提示:

这个看不看都行

队尾入队列

//队尾入队列
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);

	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}

	newnode->val = x;
	newnode->next = NULL;

	if (pq->ptail == NULL)
	{
		pq->ptail = pq->phead = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}

	pq->size++;
}

实现步骤: 

1、利用断言检测队列指针的有效性

2、malloc申请新的结点空间,并进行开辟失败的判断

3、若开辟成功则向链表结点中插入有效数据,以及下一个结点的置空

4、检测队列是否为空,若为空则将新申请的结点作为队列的第一个元素,令指向队头和队尾的指针指向该元素

5、若不为空,则将指向队尾元素的指针指向新元素,同时将指向队尾的指针向后移动指向该元素

6、完成一次队尾入队操作后,将队列元素个数加一

队头出队列

// 对头出队列
void QueuePop(Queue* pq)
{
	assert(pq);
	
	assert(pq->phead);

	QNode* del = pq->phead;
	pq->phead = pq->phead->next;
	free(del);
	del = NULL;

	if (pq->phead == NULL)
		pq->ptail = NULL;

	pq->size--;
}

实现步骤: 

1、利用断言检测队列指针的有效性

2、利用断言检测队列头元素不为空

3、利用临时指针变量删除队头结点,并将指向队头结点指针向后移动,最后释放该指针并置空

4、队头元素出队列后,若头指针变为空,则将尾指针也变为空

获取队头元素

//获取队头元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	// 
	assert(pq->phead);

	return pq->phead->val;
}

实现步骤: 

1、利用断言检测队列指针的有效性

2、利用断言检测队列头元素不为空

3、返回此时队头元素的值

获取队尾元素

//获取队头元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	// 
	assert(pq->phead);

	return pq->phead->val;
}

实现步骤: 

1、利用断言检测队列指针的有效性

2、利用断言检测队列头元素不为空

3、返回此时队尾元素的值

获取队列中有效元素个数

//获取队列中有效元素个数
int QueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}

实现步骤: 

1、利用断言检测队列指针的有效性

2、返回结构体中的size值

检测队列是否为空

//检测队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->phead == NULL;
}

实现步骤: 

1、利用断言检测队列指针的有效性

2、返回对pq->phead == NULL的判断结果,返回结果为真则队列为空,为假则队列非空

销毁队列

//销毁队列
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;
}

实现步骤: 

1、利用断言检测队列指针的有效性

2、遍历每一个队头元素并销毁,最后将头尾指针及队列元素数量均置为空

最终代码

Queue.h文件

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>

//链式结构:表示队列
typedef int QDataType;
typedef struct QueueNode
{
	QDataType val;
	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);

//检测队列是否为空
bool QueueEmpty(Queue* pq);

//销毁队列
int QueueSize(Queue* pq);

Queue.c文件

#include"Queue.h"

//初始化队列
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = 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->val = x;
	newnode->next = NULL;

	if (pq->ptail == NULL)
	{
		pq->ptail = pq->phead = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}

	pq->size++;
}

// 对头出队列
void QueuePop(Queue* pq)
{
	assert(pq);
	// 
	assert(pq->phead);

	QNode* del = pq->phead;
	pq->phead = pq->phead->next;
	free(del);
	del = NULL;

	if (pq->phead == NULL)
		pq->ptail = NULL;

	pq->size--;
}

//获取队头元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	// 
	assert(pq->phead);

	return pq->phead->val;
}

//获取队尾元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	// 
	assert(pq->ptail);

	return pq->ptail->val;
}

//检测队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->phead == NULL;
}

//获取队列中有效元素个数
int QueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}

test.c文件

#include "Queue.h"

int main()
{
	Queue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	printf("%d ", QueueFront(&q));
	QueuePop(&q);
	printf("%d ", QueueFront(&q));
	QueuePop(&q);

	QueuePush(&q, 4);
	QueuePush(&q, 5);
	while (!QueueEmpty(&q))
	{
		printf("%d ", QueueFront(&q));
		QueuePop(&q);
	}

	QueueDestroy(&q);

	return 0;
}

循环队列 

概念:循环队列是一种特殊的队列数据结构,它通过使用固定大小的数组来实现。与普通队列不同的是,在循环队列中,当尾指针(rear)达到数组末尾时,会从数组开头重新开始存储元素

优点:充分利用出队操作后释放出来的空间,避免频繁地移动元素

适用场景:循环队列常用于需要高效处理连续输入输出流数据的场景,如缓冲区、任务调度等

关于循环队列的实现放在下一篇文章......

队列的OJ题

用队列实现栈

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

具体解题思路如下:

1、题目要求使用两个队列,但队列的基本功能需要自己实现

2、利用栈的结构体存储两个队列的头尾指针及队列元素个数的信息

3、为队列申请结点空间并利用QueueInit函数初始化队列

4、 入栈时,利用if判断谁为非空队列后,将要入栈的元素尾插进非空队列中(QueueBack函数),出栈的大体过程如下图所示:

5、出栈时,为了将队列的最后一个元素先排出,就需要让原来存储有效数据的队列的前N-1个元素放入空的队列中,然后再将元队列中的最后一个元素排出,两个队列的作用是来回切换的需要利用if语句判断队列的空与非空后在进行操作,出栈的大体过程如下图所示:

6、获取栈顶元素时,只需要判断两个队列谁不为空,将不为空的队列的队尾元素返回即可

7、判断栈是否为空时,当两个队列均为空时栈才能为空,所以需要用&&

8、销毁栈时、不仅要释放掉malloc申请的内存空间,还要将两个队列一同销毁

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>

//链式结构:表示队列
typedef int QDataType;
typedef struct QueueNode
{
	QDataType val;
	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);

//检测队列是否为空
bool QueueEmpty(Queue* pq);

//销毁队列
int QueueSize(Queue* pq);



//初始化队列
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = 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->val = x;
	newnode->next = NULL;

	if (pq->ptail == NULL)
	{
		pq->ptail = pq->phead = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}

	pq->size++;
}

// 对头出队列
void QueuePop(Queue* pq)
{
	assert(pq);
	// 
	assert(pq->phead);

	QNode* del = pq->phead;
	pq->phead = pq->phead->next;
	free(del);
	del = NULL;

	if (pq->phead == NULL)
		pq->ptail = NULL;

	pq->size--;
}

//获取队头元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);

	assert(pq->phead);

	return pq->phead->val;
}

//获取队尾元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	 
	assert(pq->ptail);

	return pq->ptail->val;
}

//检测队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->phead == NULL;
}

//获取队列中有效元素个数
int QueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}

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

//初始化栈
MyStack* myStackCreate() {
    //申请结点空间
    MyStack* pst = (MyStack*)malloc(sizeof(MyStack));
    //取地址后就可以操作栈结构体中p1和p2中的内容
    QueueInit(&pst->q1);       //->的优先级大于&
    QueueInit(&pst->q2);       //->的优先级大于&
	return pst;
}

//入栈
void myStackPush(MyStack* obj, int x) {
    //如果q1队列不为空则q1队列用于存放导出的数据
    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1,x);
    }
    //如果q1队列为空则q2队列用于存放导出的数据
    else
    {
        QueuePush(&obj->q2,x);
    }
}

//出栈
int myStackPop(MyStack* obj) {
    //起始假设q1为空,q2不为空,empty指针指向空队列,noempty指向非空队列
    Queue* empty = &obj->q1;
    Queue* noempty = &obj->q2;
    //如果我们假设失败则证明q1不为空,q2为空,交换标志
    if(!QueueEmpty(&obj->q1))
    {
        empty = &obj->q2;
        noempty = &obj->q1;
    }
    
    //然后将队列中的前N-1个元素导入空队列,所以循环结束的条件就是队列中元素等于1(这个剩下的就是要出栈的元素)
    while(QueueSize(noempty) > 1)
    {
        QueuePush(empty,QueueFront(noempty));
        QueuePop(noempty);
    }

    //将队列中前N-1个元素导出后剩余的就是要出栈的元素,将该元素存储进整型变量top中
    int top = QueueFront(noempty);
    //存储完成后将该元素也进行出队列操作
    QueuePop(noempty);

    //最后返回要出栈的元素
    return top;
}

//获取栈顶元素
int myStackTop(MyStack* obj) {
    //谁不为空就获取谁的队尾元素
    if(!QueueEmpty(&obj->q1))
    {
        return QueueBack(&obj->q1);
    }
    //如果q1队列为空则q2队列用于存放导出的数据
    else
    {
        return QueueBack(&obj->q2);
    }
}

//判断栈是否为空
bool myStackEmpty(MyStack* obj) {
    //只有当两个队列均为空的时候,该栈才不会有有效数据
    return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}

//销毁栈
void myStackFree(MyStack* obj) {
    //初始化时除了malloc了一个结点,还初始化了两个队列,所以除了要将申请的结点释放还要将申请的两个队列销毁
    QueueDestroy(&obj->q1);
    QueueDestroy(&obj->q2);

    free(obj);
}

关于&pst->q1的解释:

为了操作队列,我们在初始化栈时需要将队列对象作为参数传递给函数,即&pst->q1,表示获取指针 pst 所指向的结构体中成员变量 q1 的地址(可以理解为队列q1的地址),而pst是一个指向MyStack结构体的指针,所以说就是获取MyStack结构体中成员变量的地址。

用栈实现队列

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

具体解题思路如下:

1、题目要求使用两个栈,但栈的基本功能需要自己实现

2、利用栈的结构体存储两个队列的头尾指针及队列元素个数的信息

3、为栈申请结点空间并利用STInit函数初始化栈

4、入队时,直接利用STPush函数进行入栈即可

5、先返回队头元素然后再出队,先判断用于出数据的popst栈是否为空,如果为空则将pushst栈中的数据倒顺序后放入popst栈中,利用STPush函数将pushst栈的栈顶元素放入空的popst栈中

6、出队时,用临时变量front接收返回的队头元素,然后利用STPop函数将该元素出队,最后返回该元素的值

7、判断队列是否为空时,当两个栈均为空时队列才能为空,所以需要用&&

8、销毁栈时、不仅要释放掉malloc申请的内存空间,还要将两个栈一同销毁

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
 
//支持动态增长的栈
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 data);
 
// 出栈
void STPop(ST* ps);
 
// 获取栈顶元素
STDataType STTop(ST* ps);
 
// 获取栈中有效元素个数
int STSize(ST* ps);
 
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int STEmpty(ST* ps);

// 初始化栈
void STInit(ST* pst)
{
    //首先要指向一个栈
	assert(pst);
 
	pst->a = NULL;
	pst->capacity = 0;
	pst->top = 0;    //令pop表示栈顶元素的下一个元素的下标
}
 
// 销毁栈
void STDestroy(ST* pst)
{
    //首先要指向一个栈
	assert(pst);
	
    //正常操作不再过多复述
	free(pst->a);
	pst->a = NULL;
	pst->top = 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;
	}
 
    //如果栈未满则进行入栈操作(若初始化时pop=-1,则下面两行代码交换执行顺序)
	pst->a[pst->top] = x;    //此时pop表示的是栈顶元素的下一个元素的下标 
	pst->top++;              //top表示的下标数++
}
 
//出栈
void STPop(ST* pst)
{
    //首先要指向一个栈
	assert(pst);
	//top<0表示栈为空,top=0表示没有元素入栈,存在这两种情况就不能执行出栈操作(可以提供的图理解)
	assert(pst->top > 0);
 
    //直接对top执行减减操作以获取实际数组元素下标
    pst->top--;
}
 
// 获取栈顶元素
STDataType STTop(ST* pst)
{
    //首先要指向一个栈
	assert(pst);
	//top<0表示栈为空,top=0表示没有元素入栈,存在这两种情况就不能执行出栈操作(可以提供的图理解)
	assert(pst->top > 0);
	
    //当初始化top=0时,top的值与实际数组元素下标的值之间的关系是:实际下标 = top-1
    //所以这里要进行减一操作得到实际的数组元素下标后再输出
	return pst->a[pst->top - 1];
}
 
//获取栈中有效元素个数
int STSize(ST* pst)
{
    //首先要指向一个栈
	assert(pst);
    
    //初始化top=0,则top等于多少栈中就有多少个元素
	return pst->top;
}
 
//检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int STEmpty(ST* pst)
{
	//首先要指向一个栈
	assert(pst);
	
    //如果pst->top不为空则返回结果为真,为空则返回假
	return pst->top == NULL;
}

typedef struct {
    ST pushst;
    ST popst;    
} MyQueue;

//初始化栈
MyQueue* myQueueCreate() {
    MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
    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))
    {
        //将pusust里面的数据倒转顺序后传递给popst
        while(!STEmpty(&obj->pushst))
        {
            STPush(&obj->popst, STTop(&obj->pushst));
            STPop(&obj->pushst);
        }
    }

    return STTop(&obj->popst);
}

//判断是否为空
bool myQueueEmpty(MyQueue* obj) {
    return STEmpty(&obj->popst) && STEmpty(&obj->pushst);
}

//销毁队
void myQueueFree(MyQueue* obj) {
    STDestroy(&obj->popst);
    STDestroy(&obj->pushst);
}

/**
 * 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);
*/

关于&pst->pushst和&pst->popst的解释:

~over~ 

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

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

相关文章

读像火箭科学家一样思考笔记04_第一性原理(下)

1. 来自无形规则的阻力 1.1. 无形规则 1.1.1. 僵化成规则的不必要习惯和行为 1.1.2. 不像有形的书面规则 1.1.2.1. 书面规则出现在标准操作流程中&#xff0c;可以修改或删除 1.1.3. 成文的规则可能会抗拒变革&#xff0c;但无形规则却更加顽固 1.1.4. 我们为强加在自己身…

Elasticsearch 和 LangChain 合作开发可用于生产的 RAG 模板

作者&#xff1a;Aditya Tripathi 在过去的几个月里&#xff0c;我们一直与 LangChain 团队密切合作&#xff0c;他们在推出 LangServe 和 LangChain 模板方面取得了进展&#xff01; LangChain Templates 是一组用于构建生产质量的生成式 AI 应用程序的参考架构。 你可以在此处…

从0开始学习JavaScript--JavaScript使用Promise

JavaScript中的异步编程一直是开发中的重要话题。传统的回调函数带来了回调地狱和代码可读性的问题。为了解决这些问题&#xff0c;ES6引入了Promise&#xff0c;一种更现代、更灵活的异步编程解决方案。本文将深入探讨JavaScript中如何使用Promise&#xff0c;通过丰富的示例代…

试用无线调试器PowerDebugger小记

试用无线调试器PowerDebugger小记 文章目录 试用无线调试器PowerDebugger小记引言准备软硬件环境PowerDebugger 无线调试器EVB-YTM32B1LE0-Q64 开发板 开始调试小结参考文献 引言 多年前调试智能车时&#xff0c;抱着电脑连着小车在跑道上一边跑一边看数据的经历&#xff0c;让…

vue-awesome-swiper 引入css样式文件报错等问题

引入css样式文件这个错是我最开始就有的错误&#xff0c;因为在安装vue-awesome-swiper 就会默认安装swiper。我指定了vue-awesome-swiper的版本&#xff0c;但是没指定swiper的版本&#xff0c;默认安装版本为8.0.7。 所以在引入css文件的时候报错&#xff0c;在node_modules…

车载毫米波雷达行业发展4——技术

4.1 车载毫米波雷达技术原理 毫米波雷达系统可实现距离测量、速度测量和角度测量三大基本功能。车载毫米波雷达 常用调频连续波(FMCW)雷达&#xff0c;其工作频率随时间做周期性线性变化&#xff0c;能测速和测距&#xff0c;适合做 近距离测量&#xff0c;有较高的测量精度。…

Docker发布简单springboot项目

Docker发布简单springboot项目 在IDEA工具中直接编写Dockerfile文件 FROM java:8COPY *.jar /app.jarCMD ["--server.prot 8080"]EXPOSE 8080ENTRYPOINT ["java", "-jar", "/app.jar"]将项目打包成对应的jar包&#xff0c;将Dockerf…

基于龙格-库塔算法优化概率神经网络PNN的分类预测 - 附代码

基于龙格-库塔算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于龙格-库塔算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于龙格-库塔优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对P…

cpu飙高问题,案例分析(一)

一、复习知识点&#xff1a; CPU性能指标&#xff1a; load average&#xff1a;负载&#xff0c;linux查看的时候&#xff0c;通常显示如下&#xff1a; load average后面有三段数字&#xff1a;代表了系统1分钟&#xff0c;5分钟&#xff0c;15分钟平均负载。 形象的类别可…

CommonModule.dll动态链接库(DLL)文件丢失的处理方法

方法一、手动下载修复 (1)从网站下载commonmodule.dll文件到您的电脑上。 (2)将commonmodule.dll文件复制到" X:\Windows\system32 " (X代表您系统所在目录盘符&#xff0c;如&#xff1a;C:\Windows\system32)目录下。 (3)在开始菜单中找到"运行(R)" 或…

shell 脚本变量

目录 什么是 shell shell 的两种面向对象 shell 脚本概述 脚本 &#xff08;本质为程序&#xff09; 脚本的组成 执行脚本 例题 脚本构成 脚本执行逻辑及执行方式 脚本的常见错误 编写 shell 脚本 执行脚本文件的方式 重定向 重定向操作 shell 变量的作用及类型…

智能井盖传感器功能有哪些?

智能井盖传感器是一种集成了多种先进技术的传感器设备&#xff0c;旨在强化城市的公共安全&#xff0c;确保城市基础设施的稳定运作。这种传感器具有多种功能&#xff0c;例如实时监测井盖状态、监测井下气体等是否超出阈值。借助智能井盖传感器&#xff0c;政府和城市管理部门…

C++:拷贝构造函数,深拷贝,浅拷贝

一.什么是拷贝构造函数&#xff1f; 同一个类的对象在内存中有完全相同的结构&#xff0c;如果作为一个整体进行复制&#xff08;拷贝&#xff09;是完全可行的。这个拷贝过程只需要拷贝数据成员&#xff0c;而函数成员是共用的&#xff08;只有一份拷贝&#xff09;。在建立对…

1230天,百度再见!!!

从2020年7月8日至2023年11月20日&#xff0c;在百度的工作到达了终点&#xff0c;完成了从学生向职场人的蜕变&#xff0c;是时候说再见了&#xff01; 一、成长收获 在这1230天里收获颇丰&#xff0c;下面与各位分享一下。 从技术至上到业务赋能的思想转变 相信很多人都存在“…

一个完备的手游地形实现方案

一、地形几何方案&#xff1a;Terrain 与 Mesh 1.1 目前手游主流地形几何方案分析 先不考虑 LOD 等优化手段&#xff0c;目前地形的几何方案选择有如下几种&#xff1a; 使用 Unity 自带的 Terrain使用 Unity 自带的 Terrain&#xff0c;但是等美术资产完成后使用工具转为 M…

键盘快捷键工具Keyboard Maestro mac中文版介绍

Keyboard Maestro mac是一款键盘快捷键工具&#xff0c;它可以帮助用户通过自定义快捷键来快速完成各种操作&#xff0c;提高工作效率。Keyboard Maestro支持多种快捷键组合&#xff0c;包括单键、双键、三键、四键组合等&#xff0c;用户可以根据自己的习惯进行设置。此外&…

全志H616开发版

开发板介绍&#xff1a; 二、开发板刷机 SDFormatter TF卡的格式化工具、Win32Diskimager 刷机工具 刷机镜像为&#xff1a;Orangepizero2_2.2.0_ubuntu_bionic_desktop_linux4.9.170.img 使用MobaXterm_Personal_20.3连接使用 网络配置&#xff1a;nmcli dev wifi 命令接入网…

PLC梯形图实操——风扇正反转

文章目录 1.项目内创建函数块&#xff08;FB&#xff09;2.项目内创建数据块&#xff08;DB&#xff09;2.1去除优化块访问2.2去除优化块的访问后对数据块进行编译 3.在函数块&#xff08;FB&#xff09;内实现正转反转的自锁与互锁3.1在函数块内实现电机正反转的梯形图 4.主函…

Python的os.path.join()详解

当你需要构建文件路径时&#xff0c;os.path.join() 是一个很有用的方法。这个方法会根据你的操作系统使用正确的路径分隔符&#xff08;例如&#xff0c;在 Windows 上是反斜杠 \&#xff0c;在类 Unix 系统上是正斜杠 /&#xff09;来连接路径中的各个部分。这样你就可以确保…

Django实战:从零到一构建安全高效的Web应用

目录 一、概述 二、版本控制和部署 1、Git版本控制 2、Docker部署 三、数据库配置 1、配置数据库设置 2、创建数据库模型 四、URL路由和视图 1、定义URL路由 2、创建视图 五、模板渲染 1、创建模板 2、在视图中使用模板 总结 一、概述 Django是一个高级Python W…