栈和队列循环队列(C/C++)

news2024/11/28 12:51:48

        本篇将用数组实现栈、链表实现队列以及使用数组实现循环队列,然后实现了用栈实现队列和用队列实现栈以及一些其他的栈和队列的习题,加深队栈和队列的理解。

        若只看对应所需,可直接看文章旁的目录。

1.栈

1.1栈的概念及结构

        栈:一种特殊的线性表,其中只允许在固定的一端插入和删除元素,进行数据插入和删除操作的一端被称为栈顶,另一端被称为栈底栈中的数据元素遵守先进后出LIFO(Last In First Out)的原则。

        压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶

        出栈:栈的删除操作叫做出栈,出数据也在栈顶。

        上图就是出栈和压栈的示意图。 

1.2栈的实现

        栈的实现一般可以使用数据或者链表实现,但相对而言使用数组实现更优一些,因为数组在尾上插入数据的代价比较小。

        所以本篇将使用数组实现栈。

        注:对于数组实现栈,我们可以将栈顶指针指向栈顶元素,也可以指向栈顶元素的上一个位置,这两种实现方式都是可以的。本篇的栈顶指针指向的是栈的上一个元素。两种的实现方式都有略微的不同。

        对于栈的实现,对于较难理解的将给出注释,如下:

1.2.1 Stack.h

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>

//定义元素数据类型
typedef int STDataType;

//栈的数据结构
typedef struct Stack {
	STDataType* arr;
	int top;
	int capacity;
}Stack;

//栈的初始化以及销毁
void STInit(Stack* ps);
void STDestroy(Stack* ps);

//压栈与出栈
void STPush(Stack* ps, STDataType x);
void STPop(Stack* ps);

//返回栈顶元素/栈的尺寸/栈是否为NULL
STDataType STTop(Stack* ps);
int STSize(Stack* ps);
bool STEmpty(Stack* ps);

1.2.2 Stack.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "Stack.h"

void STInit(Stack* ps) {
	assert(ps);
	ps->arr = NULL;
	ps->capacity = 0;
	ps->top = 0;
}

void STDestroy(Stack* ps) {
	assert(ps);
	free(ps->arr);
	ps->arr = NULL;
	ps->capacity = 0;
	ps->top = 0;
	ps = NULL;
}

void STPush(Stack* ps, STDataType x) {
	assert(ps);
	//判断栈是否需要扩容
	if (STSize(ps) == ps->capacity) {
		//三目操作符进行扩容,第一次的容量为4,以后每次扩容一倍
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDataType* tmp = (STDataType*)realloc(ps->arr, newcapacity * sizeof(STDataType));
		if (tmp == NULL) {
			perror("realloc:");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newcapacity;
	}
	ps->arr[ps->top] = x;
	ps->top++;
}

void STPop(Stack* ps) {
	assert(ps);
	assert(!STEmpty(ps));
	//出栈只需要将栈的尺寸减小,下次压栈的元素直接进行覆盖
	ps->top--;
}

STDataType STTop(Stack* ps) {
	assert(ps);
	assert(!STEmpty(ps));
	STDataType ret = ps->arr[ps->top - 1];
	return ret;
}

int STSize(Stack* ps) {
	assert(ps);
	//栈顶的编号其实就是栈的尺寸
	return ps->top;
}

bool STEmpty(Stack* ps) {
	assert(ps);
	return ps->top == 0;
}

1.2.3 All of Code

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>

//定义元素数据类型
typedef int STDataType;

//栈的数据结构
typedef struct Stack {
	STDataType* arr;
	int top;
	int capacity;
}Stack;

//栈的初始化以及销毁
void STInit(Stack* ps);
void STDestroy(Stack* ps);

//压栈与出栈
void STPush(Stack* ps, STDataType x);
void STPop(Stack* ps);

//返回栈顶元素/栈的尺寸/栈是否为NULL
STDataType STTop(Stack* ps);
int STSize(Stack* ps);
bool STEmpty(Stack* ps);

void STInit(Stack* ps) {
	assert(ps);
	ps->arr = NULL;
	ps->capacity = 0;
	ps->top = 0;
}

void STDestroy(Stack* ps) {
	assert(ps);
	free(ps->arr);
	ps->arr = NULL;
	ps->capacity = 0;
	ps->top = 0;
	ps = NULL;
}

void STPush(Stack* ps, STDataType x) {
	assert(ps);
	//判断栈是否需要扩容
	if (STSize(ps) == ps->capacity) {
		//三目操作符进行扩容,第一次的容量为4,以后每次扩容一倍
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDataType* tmp = (STDataType*)realloc(ps->arr, newcapacity * sizeof(STDataType));
		if (tmp == NULL) {
			perror("realloc:");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newcapacity;
	}
	ps->arr[ps->top] = x;
	ps->top++;
}

void STPop(Stack* ps) {
	assert(ps);
	assert(!STEmpty(ps));
	//出栈只需要将栈的尺寸减小,下次压栈的元素直接进行覆盖
	ps->top--;
}

STDataType STTop(Stack* ps) {
	assert(ps);
	assert(!STEmpty(ps));
	STDataType ret = ps->arr[ps->top - 1];
	return ret;
}

int STSize(Stack* ps) {
	assert(ps);
	//栈顶的编号其实就是栈的尺寸
	return ps->top;
}

bool STEmpty(Stack* ps) {
	assert(ps);
	return ps->top == 0;
}

int main() {
	Stack st;
	STInit(&st);
	STPush(&st, 1);
	STPush(&st, 2);
	STPush(&st, 3);
	while (!STEmpty(&st)) {
		STDataType top = STTop(&st);
		STPop(&st);
		printf("%d ", top);
	}
	STPush(&st, 4);
	STPush(&st, 5);
	while (!STEmpty(&st)) {
		STDataType top = STTop(&st);
		STPop(&st);
		printf("%d ", top);
	}
	STDestroy(&st);
	return 0;
}

        测试结果: 

2.队列

2.1 队列的概念及结构

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

        入队列:进行插入操作的一端称为队尾。

        出队列:进行删除操作的一端称为队头。 

2.2队列的实现 

        对于队列的实现,都可以使用数组以及链表结构,但是使用链表结构实现出队以及入队将更方便,同时还会节省更多的空间。

        如上图所示,当使用数组实现队列时,由于开辟的空间是固定的,所以出队时将会浪费一些空间。 

2.2.1 Queue.h

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

typedef int QDataType;

//队列节点的数据结构
typedef struct Node {
	QDataType val;
	struct Node* next;
}QNode;

//队列的队首指针、队尾指针、尺寸
typedef struct Queue {
	int size;
	QNode* phead;
	QNode* ptail;
}Queue;

//队列的初始化/销毁
void QueueInit(Queue* pQ);
void QueueDestory(Queue* pQ);

//队列的入队/出队
void QueuePush(Queue* pQ, QDataType x);
void QueuePop(Queue* pQ);

//返回队首元素/队尾元素
QDataType QueueFront(Queue* pQ);
QDataType QueueBack(Queue* pQ);

//判断队列是否为NULL/返回队列的大小
bool QueueEmpty(Queue* pQ);
int QueueSize(Queue* pQ);

2.2.2 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 QueueDestory(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:");
		exit(1);
	}
	newnode->val = x;
	newnode->next = NULL;
	if (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(pQ->phead);
	QNode* cur = pQ->phead;
	pQ->phead = pQ->phead->next;
	free(cur);
	cur = NULL;
	pQ->size--;
}

QDataType QueueFront(Queue* pQ) {
	assert(pQ);
	assert(pQ->phead);
	return pQ->phead->val;
}

QDataType QueueBack(Queue* pQ) {
	assert(pQ);
	assert(pQ->phead);
	return pQ->ptail->val;
}

bool QueueEmpty(Queue* pQ) {
	assert(pQ);
	return pQ->phead == NULL;
}

int QueueSize(Queue* pQ) {
	assert(pQ);
	return pQ->size;
}

2.2.3 All of Code

 

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

typedef int QDataType;

//队列节点的数据结构
typedef struct Node {
	QDataType val;
	struct Node* next;
}QNode;

//队列的队首指针、队尾指针、尺寸
typedef struct Queue {
	int size;
	QNode* phead;
	QNode* ptail;
}Queue;

//队列的初始化/销毁
void QueueInit(Queue* pQ);
void QueueDestory(Queue* pQ);

//队列的入队/出队
void QueuePush(Queue* pQ, QDataType x);
void QueuePop(Queue* pQ);

//返回队首元素/队尾元素
QDataType QueueFront(Queue* pQ);
QDataType QueueBack(Queue* pQ);

//判断队列是否为NULL/返回队列的大小
bool QueueEmpty(Queue* pQ);
int QueueSize(Queue* pQ);

void QueueInit(Queue* pQ) {
	assert(pQ);
	pQ->phead = pQ->ptail = NULL;
	pQ->size = 0;
}

void QueueDestory(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:");
		exit(1);
	}
	newnode->val = x;
	newnode->next = NULL;
	if (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(pQ->phead);
	QNode* cur = pQ->phead;
	pQ->phead = pQ->phead->next;
	free(cur);
	cur = NULL;
	pQ->size--;
}

QDataType QueueFront(Queue* pQ) {
	assert(pQ);
	assert(pQ->phead);
	return pQ->phead->val;
}

QDataType QueueBack(Queue* pQ) {
	assert(pQ);
	assert(pQ->phead);
	return pQ->ptail->val;
}

bool QueueEmpty(Queue* pQ) {
	assert(pQ);
	return pQ->phead == NULL;
}

int QueueSize(Queue* pQ) {
	assert(pQ);
	return pQ->size;
}

int main() {
	Queue queue;
	QueueInit(&queue);
	QueuePush(&queue, 1);
	QueuePush(&queue, 2);
	printf("%d ", QueueFront(&queue));
	QueuePop(&queue);
	QueuePush(&queue, 3);
	QueuePush(&queue, 4);
	printf("%d ", QueueFront(&queue));
	QueuePop(&queue);
	QueuePush(&queue, 5);
	while (!QueueEmpty(&queue)) {
		printf("%d ", QueueFront(&queue));
		QueuePop(&queue);
	}
	QueueDestory(&queue);
	return 0;
}

        测试结果:

2.3循环队列的实现 

        在上文中我们提到,当我们使用数组实现队列的时候,会出现一些空间浪费的情况,这是因为出队时,出队下标将向后移动,前面的空间则浪费,当我们使用循环链表就可以很好的解决该问题。

        循环链表:将数组的首尾相连,组成的一个特殊结构。我们用两个指针来表示队列的队首和队尾,front 表示队首,back表示队尾的下一个元素。

        为了能使Q.front=Q.back来区别队列是否为空还是满,我们常常认为出现作图时的情况即为队满的情况,此时:Q.front=Q.back+1;

        对于循环队列的代码实现如下,对于代码的解释在注释给出。

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

typedef struct {
    int* arr;
    int front;
    int back;
    int k;
} MyCircularQueue;

//循环队列的初始化
MyCircularQueue* myCircularQueueCreate(int k) {
    //堆上分配空间,才能在出函数时仍然存在
    MyCircularQueue* Queue=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    if(Queue==NULL){
        perror("malloc:");
        exit(1);
    }
    //分配k+1个空间,便于我们判断是否为满队列还是空队列
    Queue->arr=(int*)malloc(sizeof(int)*(k+1));
    Queue->front=Queue->back=0;
    Queue->k=k;
    return Queue;
}

//判断队列是否为NULL队列
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->front==obj->back;
}

//判断队列是否为满队列
bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return obj->front==(obj->back+1)%(obj->k+1);
}

//在队列中加入元素
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull(obj)){
        return false;
    }
    else{
        obj->arr[obj->back]=value;
        obj->back++;
        obj->back%=(obj->k+1);
        return true;
    }
}

//队列中删除元素
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj)){
        return false;
    }
    else{
        obj->front++;
        obj->front%=(obj->k+1);
        return true;
    }
}

//返回队首元素
int myCircularQueueFront(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj)){
        return -1;
    }
    return obj->arr[obj->front];
}

//返回队尾元素
int myCircularQueueRear(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj)){
        return -1;
    }
    //对于队尾元素的返回,需要注意是否为队列中第k+1个元素,有以下两种写法
    //return obj->arr[(obj->back+obj->k)%(obj->k+1)];
    if(obj->back==0){
        return obj->arr[obj->k];
    }else{
        return obj->arr[obj->back-1];
    }
}

//释放空间
void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->arr);
    free(obj);
}

        对于以上循环队列的实现,其实是一个习题,链接如下:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode.cn/problems/design-circular-queue/description/         测试结果:

3.栈与队列相关习题

        注:在习题中使用的函数都是以上的代码函数。

3.1队列实现栈

        使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppop 和 empty)。 

        习题链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode.cn/problems/implement-stack-using-queues        若要使用两个队列实现栈的操作,最难的两个操作及就是出栈和压栈。

        对于压栈,我们只需将要压栈的元素压入一个非空队列,另一个队列保存空。

        对于出栈,我们只需要除最后一个元素的队列进入另一个空队列,然后在删除最后一个元素及就实现了出栈。代码如下:

typedef struct {
    Queue p1;
    Queue p2;
} MyStack;


MyStack* myStackCreate() {
    MyStack* stack=(MyStack*)malloc(sizeof(MyStack));
    if(stack==NULL){
        perror("stack's malloc:");
        exit(1);
    }
    QueueInit(&stack->p2);
    QueueInit(&stack->p1);
    return stack;
}

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

int myStackPop(MyStack* obj) {
    Queue* empty=&obj->p1;
    Queue* nonempty=&obj->p2;
    if(!QueueEmpty(empty)){
        empty=&obj->p2;
        nonempty=&obj->p1;
    } 
    while(QueueSize(nonempty)>1){
        QueuePush(empty,QueueFront(nonempty));
        QueuePop(nonempty);
    }
    int top=QueueFront(nonempty);
    QueuePop(nonempty);
    return top;
}

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

bool myStackEmpty(MyStack* obj) {
    return QueueEmpty(&obj->p1)&&QueueEmpty(&obj->p2);
}

void myStackFree(MyStack* obj) {
    QueueDestory(&obj->p1);
    QueueDestory(&obj->p2);
    free(obj);
    obj=NULL;
}

        测试结果:

3.2栈实现队列 

        使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(pushpoppeekempty):

        习题链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode.cn/problems/implement-queue-using-stacks/         使用两个栈实现队列,主要思想为:一组数据进栈两次即可实现先进先出。

        一个栈作为入队栈,只用来将数据压入栈;

        另一个栈作为出队栈,只用来将数据弹出栈;

        当我们需要将数据出队时,我们将入队栈的数据全部压入出队栈,此时出栈的顺序正确,注意:这里只有当出队栈为空时才能将入队栈的数据压入出队栈,要不然会导致出队的顺序错乱。

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

MyQueue* myQueueCreate() {
    MyQueue* Queue=(MyQueue*)malloc(sizeof(MyQueue));
    if(Queue==NULL){
        perror("queue malloc:");
        exit(1);
    }
    STInit(&Queue->pushst);
    STInit(&Queue->popst);
    return Queue;
}

void myQueuePush(MyQueue* obj, int x) {
    //将元素压入push栈
    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);
        }
    }
    int front=STTop(&obj->popst);
    return front;
}

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

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

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

        测试结果: 

3.3有效的括号匹配

        给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

        习题链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode.cn/problems/valid-parentheses/description/         对于该题的实现,主要思想是将所有的左括号压入栈,只要遇到右括号,将栈的中左括号弹出,判断是否配对,若不配对则返回ERROR,一直配对和判断,若最后栈为NULL,说明完全配对,则我们可以判断括号匹配。代码如下:

bool isValid(char* s) {
    Stack st;
    STInit(&st);
    while(*s){
        if(*s=='['||*s=='('||*s=='{'){
            STPush(&st,*s);
        }else{
            if(STEmpty(&st)){
                STDestroy(&st);
                return false;
            }
            char ch=STTop(&st);
            STPop(&st);
            if((ch=='('&&*s!=')')||(ch=='{'&&*s!='}')||(ch=='['&&*s!=']')){
                return false;
            }
        }
        s++;
    }
    bool ret=STEmpty(&st);
    STDestroy(&st);
    return ret;
}

        测试结果:

 

 

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

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

相关文章

8.JS中的== 操作符的强制类型转换规则

对于 来说&#xff0c;如果对比双方的类型不一样&#xff0c;就会进行类型转换。假如对比 x 和 y 是否相同&#xff0c;就会进行如下判断流程&#xff1a; 首先会判断两者类型是否相同&#xff0c;类型相同的话就比较两者的大小&#xff1b;类型不相同的话&#xff0c;就会进…

【lesson52】 线程概念

文章目录 线程学习前的了解知识理解线程 线程学习前的了解知识 线程在进程内部执行&#xff0c;是OS调度的基本单位 OS可以做到让进程对进程地址空间进行资源的细粒度划分 比如malloc一块内存空间&#xff0c;我们拿到的一般都是起始位置&#xff0c;但是最终位置我们一般都不…

突发!AI大牛Andrej Karpathy离开OpenAI

刚刚&#xff0c;AI大牛Andrej Karpathy官宣了一条重要消息&#xff1a;他昨天已经从OpenAI离职&#xff0c;不过这中间没有什么戏剧性冲突&#xff0c;他只是想去尝试一下自己的个人项目。 Karpathy在官宣离职的推文中写道&#xff0c;「是的&#xff0c;我昨天离开了OpenAI。…

base64------ “ )!@#$%^*( ”代换 “0-9”

“ )!#$%^&*( ”代换 “0-9” ——[安洵杯 2019]JustBase 题目&#xff1a; VGhlIGdlbxvZ#kgbYgdGhlIEVhcnRoJ#Mgc#VyZmFjZSBpcyBkb!pbmF)ZWQgYnkg dGhlIHBhcnRpY#VsYXIgcHJvcGVydGllcyBvZiB#YXRlci$gUHJlcVudCBvbiBFYXJ)aCBp biBzbxpZCwgbGlxdWlkLCBhbmQgZFzZW(!…

celery异步框架的使用

文章目录 celery的介绍celery的架构celery的快速使用celery 包结构celery 定时 异步 延迟任务django使用celery celery的介绍 celery是什么&#xff1f; -翻译过来是芹菜 -官网&#xff1a;https://docs.celeryq.dev/en/stable/ -吉祥物&#xff1a;芹菜 -分布式的异步任务框架…

计算机网络概述习题拾遗

学习目标&#xff1a; 自下而上第一个提供端到端服务的层次 路由器、交换机、集线器实现的功能层 TCP/IP体系结构的网络接口层对应OSI体系结构的哪两个层次 分组数量对总时延的影响 如果这篇文章对您有帮助&#xff0c;麻烦点赞关注支持一下动力猿吧&#xff01; 学习内容…

《剑指 Offer》专项突破版 - 面试题 44 : 二叉树中每层的最大值(两种方法 + C++ 实现)

目录 前言 一、只用一个队列 二、使用两个队列 前言 题目链接&#xff1a;LCR 044. 在每个树行中找最大值 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 输入一棵二叉树&#xff0c;请找出二叉树中每层的最大值。例如&#xff0c;输入下图中的二叉树&#x…

VueCLI核心知识综合案例TodoList

目录 1 拿到一个功能模块首先需要拆分组件&#xff1a; 2 使用组件实现静态页面的效果 3 分析数据保存在哪个组件 4 实现添加数据 5 实现复选框勾选 6 实现数据的删除 7 实现底部组件中数据的统计 8 实现勾选全部的小复选框来实现大复选框的勾选 9 实现勾选大复选框来…

RIDERS: Radar-Infrared Depth Estimation for Robust Sensing

RIDERS: 恶劣天气及环境下鲁棒的密集深度估计 论文链接&#xff1a;https://arxiv.org/pdf/2402.02067.pdf 作者单位&#xff1a;浙江大学, 慕尼黑工业大学 代码链接&#xff1a;https://github.com/MMOCKING/RIDERS 1. 摘要&#xff08;Abstract&#xff09; 恶劣的天气条件, …

Spring Boot 笔记 019 创建接口_文件上传

1.1 创建阿里OSS bucket OSS Java SDK 兼容性和示例代码_对象存储(OSS)-阿里云帮助中心 (aliyun.com) 1.2 编写工具类 package com.geji.utils;import com.aliyun.oss.ClientException; import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import com.aliyun…

Waymo数据集下载与使用

在撰写论文时&#xff0c;接触到一个自动驾驶数据集Waymo Dataset 论文链接为&#xff1a;https://arxiv.org/abs/1912.04838v7 项目链接为&#xff1a;https://github.com/waymo-research/waymo-open-dataset 数据集链接为&#xff1a;https://waymo.com/open waymo提供了两种…

K8sGPT 的使用

K8sGPT 介绍 k8sgpt 是一个扫描 Kubernetes 集群、诊断和分类问题的工具。它将 SRE 经验编入其分析器中&#xff0c;并帮助提取最相关的信息&#xff0c;通过人工智能来丰富它。它还可以与 OpenAI、Azure、Cohere、Amazon Bedrock 和本地模型结合使用。 K8sGPT Github 地址 …

助眠神器小程序源码|白噪音|小睡眠|微信小程序前后端开源

安装要求和说明后端程序运行环境&#xff1a;NginxPHP7.4MySQL5.6 PHP程序扩展安装&#xff1a;sg11 网站运行目录设置为&#xff1a;public 伪静态规则选择&#xff1a;thinkphp 数据库修改文件路径&#xff1a;/config/database.php需要配置后端的小程序配置文件&#xff0c;…

Java中锁的应用

文章目录 前言一、场景描述二、加锁1.synchronized2.ReentrantLock 三、扩展1.ThreadLocal 总结 前言 在多线程场景下&#xff0c;多个线程同时对共享变量进行操作是存在风险的&#xff0c;这时候就需要加锁来保证数据的正确性。 一、场景描述 我这里有5个无人机,准备卖到乌克…

Spring Boot 笔记 009 创建接口_更新用户基本信息

1.1.1 给User实体类添加校验 package com.geji.pojo;import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import jakarta…

【开源图床】使用Typora+PicGo+Gitee搭建个人博客图床

准备工作&#xff1a; 首先电脑得提前完成安装如下&#xff1a; 1. nodejs环境(node ,npm):【安装指南】nodejs下载、安装与配置详细教程 2. Picgo:【安装指南】图床神器之Picgo下载、安装与配置详细教程 3. Typora:【安装指南】markdown神器之Typora下载、安装与无限使用详细教…

Linux网络基础1

目录 计算机网络背景协议OSI七层模型TCP/IP五层&#xff08;四层&#xff09;模型网络传输基本流程以太网通信原理IP地址理解 计算机网络背景 到目前为止&#xff0c;我们之前所有的编程都是单机的&#xff0c;不是多机互联。以前计算机被发明的时候是为了军事用途&#xff0…

x86汇编通用寄存器用途一览

文章目录 写在前面通用寄存器参考资料 写在前面 intel官方文档链接&#xff1a;Intel64和IA-32架构软件开发者手册 具体在Combined Volume Set of Intel 64 and IA-32 Architectures Software Developer’s Manuals这本手册 &#xff08;五千页我的天。。。&#xff09; 不想…

FastAI 之书(面向程序员的 FastAI)(二)

原文&#xff1a;www.bookstack.cn/read/th-fastai-book 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第三章&#xff1a;数据伦理 原文&#xff1a;www.bookstack.cn/read/th-fastai-book/9bc6d15b4440b85d.md 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4…

中小学信息学奥赛CSP-J认证 CCF非专业级别软件能力认证-入门组初赛模拟题第二套(选择题)

CSP-J入门组初赛模拟题二 1、在计算机内部用来传送、存贮、加工处理的数册或指令都是以()形式进行的 A、二进制 B、八进制 C、十进制 D、智能拼音 答案&#xff1a;A 考点分析&#xff1a;主要考查小朋友们计算机相关知识&#xff0c;在计算机中都是采用二进制运算&#…