【C语言实现:用队列模拟栈与用栈模拟队列(LeetCode 225 232)】

news2024/12/15 5:29:43

在这里插入图片描述

LeetCode刷题记录
  • 🌐 我的博客主页:iiiiiankor
  • 🎯 如果你觉得我的内容对你有帮助,不妨点个赞👍、留个评论✍,或者收藏⭐,让我们一起进步!
  • 📝 专栏系列:LeetCode 刷题日志
  • 🌱 文章内容来自我的学习与实践经验,如果你有任何想法或问题,欢迎随时在评论区交流讨论。让我们一起探索更多的可能!🚀

💚文章目录💚

  • ✨前言✨
  • ☢️注意☢️
  • 🚀LeetCode225.用队列实现栈
    • 一、🌟题目描述🌟
    • 二、🎨分析🎨
    • 三、💥题解💥
      • 栈"的结构定义
      • Push接口
      • Pop接口
      • 获取栈顶元素
      • 判断栈是否为空
      • 释放free
      • ✏️总代码✏️
  • 🚀LeetCode232.用栈实现队列
    • 一、🌟题目描述🌟
    • 二、🎨分析🎨
    • 三、💥题解💥
      • 模拟队列的结构
      • 初始化队列
      • Push
      • Pop
      • 获取队头元素
      • 判断是不是空
      • 释放
      • ✏️总代码✏️

✨前言✨

首先我们可以先复习一下相关性质:

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

实现方法:1. 数组(顺序表) 2.链表
在这里插入图片描述

  • 队列

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
实现:1.链表(更优)2.数组(较差)

在这里插入图片描述

☢️注意☢️

C语言中并不想C++或者Java等高级语言那样,库中有封装好的栈和队列
所以我们用C做这些题的时候,都必须先把栈或者队列写出来,才能做题!
这也是用C刷题的很恶心的地方
但是 也能巩固我们的知识不是嘛?

🚀LeetCode225.用队列实现栈

链接:LeetCode225.用队列实现栈

一、🌟题目描述🌟

在这里插入图片描述

二、🎨分析🎨

我们知道,队列是先进先出,而栈是后进先出,那么怎么用队列实现栈呢?
我们通过画图来分析:

如果给你一个不为空的队列,我们叫他noempty
在这里插入图片描述
这个队列是 按照 1 2 3 4 的顺序放入的数据
所以 如果是队列的话 那么出队列的顺序也是 1 2 3 4
但是如果想要实现栈,那么第一个出去的数据应该是4
我们怎么实现呢?
如果我们还有一个空的队列,我们叫他empty
我们把1 2 3 放到empty里面,那么noempty里就只剩下了 4,如图:
在这里插入图片描述
这样,noempty的队头就是4 我们直接对noempty进行pop
然后 队列的性质是先进先出,所以在empty中也是 原来的1 2 3顺序
empty出队列的顺序也是1 2 3
所以 我们只需要把empty中的元素再倒回noempty
我们再观察noempty,是不是就完成了栈的后进先出的性质!!!
(因为 4 是最后进入的)
在这里插入图片描述
综上所述,其实empty就是用来倒数据的!
因此我们要时刻保证一个是空队列,另一个是非空队列
这道题目实际上就是利用一个空队列和队列的相关性质,来实现栈的 后进先出的!

三、💥题解💥

栈"的结构定义

这里的“栈” 是我们目标实现的那个栈
  • 结构需要包含两个队列

    注意: 此类型题目的结构比较复杂
    因为我们使用链表实现的栈,所以“栈”中包含的队列的结构中还有

  • 链表头节点

  • 链表尾节点

“栈”的结构

//这里是匿名结构体 因为有typedef 后面可以使用匿名结构体
typedef struct {
    //结构中包含两个队列
    Queue q1;
    Queue q2;
} MyStack;

队列的结构:

typedef struct Queue {
	size_t size;//利用一个变量去标识队列的大小
	QNode* head;//队列的头节点
	QNode* tail;//队列的尾节点
}Queue;

Push接口

由于我们需要保持一个队列为空,另一个队列不为空
对于push接口,我们只需要判断哪一个队列不为空
然后向该队列push数据就可以了

Pop接口

如果要pop数据,如1 2 3 4 5
模拟实现栈,所以要出栈,也就是删除栈顶
而栈顶就是队列的队尾
所以要删除5
只需要把前面一个个数据挪动到空队列
直接让5出队就可以了

注意这里题目让你返回pop掉的元素!

获取栈顶元素

显示栈顶元素
只需要找到不为空的队列就可以了
这里我们不需要考虑如果两个队列都为空了怎么办
只要完成他给的接口就可以了!
测试用例一定是正确合理的! 不会出现空了还让你调用这个函数的情况
: 测试用例就是看你逻辑正不正确!

判断栈是否为空

因为我们的栈是用两个队列来实现的
所以 如果两个队列都为空,那么说明栈为空!

释放free

  1. 首先把结构中包含的两个队列释放掉
  2. 然后把该结构释放掉

✏️总代码✏️

// 用队列实现栈

typedef int QDataType;
//定义队列节点的结构  
typedef struct QueueNode {

    struct QueueNode* next;
    QDataType val;//队列中的数据
}QNode;

//利用封装一个结构
typedef struct Queue {
    size_t size;//利用一个变量去标识队列的大小
    QNode* head;//队列的头节点
    QNode* tail;//队列的尾节点
}Queue;

//初始化
void QueueInit(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 QueueDestory(Queue* pq);


//初始化
void QueueInit(Queue* pq)
{
    assert(pq);
    //头节点和尾节点都设置为空即可
    pq->head = pq->tail = NULL;
    pq->size = 0;

}
//入队列
void QueuePush(Queue* pq, QDataType x)
{
    assert(pq);
    QNode* newnode = (QNode*)malloc(sizeof(QNode));
    if (newnode == NULL)
    {
        printf("malloc fail!");
        exit(-1);
    }
    newnode->next = NULL;
    newnode->val = x;
    //如果队列为空
    if (pq->tail == NULL)//也可以使用head==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)//这里需要用head的next
    {
        free(pq->head);
        pq->head = pq->tail = NULL;
        pq->size--;//队列元素个数减一
    }
    else
    {
        QNode* next = pq->head->next;
        free(pq->head);
        pq->head = next;
        pq->size--;
    }
}
//获取队头元素
QDataType QueueFront(Queue* pq)
{
    assert(pq);
    //如果队列为空 无法获取!
    assert(!QueueEmpty(pq));

    return pq->head->val;
}
//获取队尾元素
QDataType QueueBack(Queue* pq)
{
    assert(pq);
    assert(!QueueEmpty(pq));

    return pq->tail->val;
}
//获取队列中元素个数
int QueueSize(Queue* pq)
{
    assert(pq);
    return pq->size;
}
//检测队列是否为空
bool QueueEmpty(Queue* pq)
{
    assert(pq);
    //如果 head为空 返回真 否则返回假
    return pq->head == NULL;
}
//销毁队列
void QueueDestory(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;
}

/*****************************************/
/*  题解代码   */
typedef struct {
    //结构中包含两个队列
    Queue q1;
    Queue q2;
} MyStack;

//初始化
MyStack* myStackCreate() {
    //首先需要开辟一个stack
    MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
    //然后对开辟的Mystack中的q1和q2初始化
    QueueInit(&obj->q1);
    QueueInit(&obj->q2);

    //然后需要返回obj
    return obj;
}

void myStackPush(MyStack* obj, int x) {
    //如果q1不为空 那么就向q1里面插入数据
    if (!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1, x);
    }
    else//否则就向q2里面插入数据
    {
        QueuePush(&obj->q2, x);
    }
}

int myStackPop(MyStack* obj) {
    //首先需要判断哪一个不为空
    //先假设q1为空 q2不为空
    Queue* empty = &obj->q1;
    Queue* noempty = &obj->q2;
    //如果假设错了 就改一下
    if (!QueueEmpty(&obj->q1))
    {
        empty = &obj->q2;
        noempty = &obj->q1;
    }

    //然后就把非空队列的数据导入到空队列 知道非空队列还有一个数据
    while (QueueSize(noempty) > 1)
    {
        //把非空队列的队头 push到空队列
        QueuePush(empty, QueueFront(noempty));
        QueuePop(noempty);
    }

    //因为对于栈顶元素需要返回和删除
    //所以先把栈顶元素记录一下啊
    int top = QueueFront(noempty);
    QueuePop(noempty);
    return top;
}

int myStackTop(MyStack* obj) {
    //既然是显示栈顶元素
    //那就需要找到非空队列
    //显示非空队列的队尾就可以了

    //如果队列q1不为空
    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) {
    //1. 释放Mystackj里面包含的q1 和 q2 (他们里面也有malloc的节点)
    //2. 释放 Mystack
    QueueDestory(&obj->q1);
    QueueDestory(&obj->q2);
    free(obj);
}

🚀LeetCode232.用栈实现队列

链接:LeetCode232.用栈实现队列

一、🌟题目描述🌟

在这里插入图片描述

二、🎨分析🎨

思考:
这个题会不会和上一道题很类似?
我们知道 栈的性质是 后进先出,而队列的性质是先进先出
那么怎么让最先进去的最先出来呢?
画图分一下:
在这里插入图片描述

显然 最先入栈的是:1,那么如何让1 先出栈呢?
那么我们是不是可以这样?
把左边的栈的元素全部push到右边的空栈,因为栈是从栈顶出栈
所以 入右边的栈的顺序是4-3-2-1
变成了这样:
在这里插入图片描述
这时候,如果想溢出1,只需要pop一下右边的栈就可以了!
然后,我们是不是还要把 剩下的元素倒回原来的左边的栈呢?
注意,这里和上面那个题不一样的地方就在这里!
如果我们把右边的栈的数据倒回左边的栈,变成这样:
在这里插入图片描述
这时候如果再出栈,是不是还要重复把左边的栈的数据 重新push到右边的栈?
这无疑增加了工作量!
由于栈有着后进先出的特殊性质,所以 我们只要把左边的栈的数据push到右边的栈,右边的栈中就可以不断的pop(因为此时元素的顺序已经颠倒了!,符合先进先出了)
所以,导入到右边的栈之后,不需要再回来了!!!
然后 怎么push呢?,我们直接向左边的栈中push就可以了!!
也就是说:左边的栈用来push,我们叫做pushst,右边的栈用来pop,我们叫做popst
如果,popst已经空了,那么再把pushst里面的数据push到popst 就可以了!

总结:

	- 栈的性质和队列不一样,因为队列是先进先出
所以把一个数据从一个队列push到另一个队列之后,原来的元素顺序不会发生改变
所以需要在倒回来

	- 而栈的性质不一样,栈是后进先出
所以把`pushst`里的数据导入到`popst`之后,数据的顺序发生颠倒
所以,由于已经颠倒过来,把`popst`里的数据进行pop,就相当于队列的出队!
而不需要再倒回`pushst`的原因是因为: 这时候的`popst`里的数据顺序恰好是出队顺序
而如果重新导入`pushst`,那么再pop数据的时候,还需要把数据先push到`popst`中

	- 这样,如果我们想push数据,直接push到`pushst`中,
当`popst`空的时候,把`pushst`中数据导入到`popst`中,从而实现继续出队!

也就是说: pushst控制入队,popst控制出队

这个结构就相当于
在这里插入图片描述

三、💥题解💥

模拟队列的结构

包含两个栈

//匿名结构体的使用 可以利用typedef!
typedef struct {
    ST pushst;
    ST popst;
} MyQueue;

初始化队列

首先malloc一个 ‘队列’
然后要初始化 队列中的两个栈
pushst用来push
popst用来pop

MyQueue* myQueueCreate() {
    MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));
    //初始化两个栈
    StackInit(&obj->pushst);
    StackInit(&obj->popst);
    return obj;
}

Push

这样其实 push就很简单了
只需要向栈pushst里直接push就可以了!

void myQueuePush(MyQueue* obj, int x) {
    //入队统一在push栈中入数据
    StackPush(&obj->pushst,x);
}

Pop

pop比较麻烦,但也很简单
因为我们首先判断popst是不是为空
如果为空,那么pushst中的数据push到popst
否则直接poppopst

int myQueuePop(MyQueue* obj) {
    //出栈 是对pop进行的
    //如果popst为空 那么首先把pushst里的数据导入到popst
    if(StackEmpty(&obj->popst))
    {
         while(!StackEmpty(&obj->pushst))
         {
             StackPush(&obj->popst,StackTop(&obj->pushst));
             StackPop(&obj->pushst);
         }
    }
    //需要记录队尾 并返回
    int qtail=StackTop(&obj->popst);
    //出队
    StackPop(&obj->popst);
    //返回队尾元素
    return qtail;
    
   
}

获取队头元素

由于popst的栈顶就相当于队头,所以直接返回popst的栈顶就可以了!
注意:需要判断一下popst是不是为空!
如果为空 需要把pushst中的数据 先 push到popst

int myQueuePeek(MyQueue* obj) {
    //队列的头相当于 popst的栈顶
    //首先判断是不是空 如果是空 导入到popst
    if(StackEmpty(&obj->popst))
    {
        while(!StackEmpty(&obj->pushst))
         {
             StackPush(&obj->popst,StackTop(&obj->pushst));
             StackPop(&obj->pushst);
         }
    }

    return StackTop(&obj->popst);
}

判断是不是空

显然如果两个栈都为空 说明队列为空

bool myQueueEmpty(MyQueue* obj) {
    //什么时候为空呢?
    //显然 如果两个栈都为空 说明队列为空
    return StackEmpty(&obj->pushst) && StackEmpty(&obj->popst);
}

释放

  1. 首先释放两栈
  2. 然后释放队列结构
void myQueueFree(MyQueue* obj) {
    //首先释放两个栈
    //然后释放MyQueue
    StackDestory(&obj->pushst);
    StackDestory(&obj->popst);
    free(obj);
}

✏️总代码✏️

typedef int STDataType;
typedef struct Stack {
	//动态开辟数组
	STDataType* a;
	int top;//栈顶
	int capacity;//容量
}ST;
//初始化
void StackInit(ST* ps);
//压栈
void StackPush(ST* ps, STDataType x);
//出栈
void StackPop(ST* ps);
//获取栈中有效元素个数
int StackSize(ST* ps);
//显示栈顶元素
STDataType StackTop(ST* ps);
//检测栈是否为空
bool StackEmpty(ST* ps);
//销毁
void StackDestory(ST* ps);

//初始化
void StackInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->capacity = ps->top = 0;
}
//压栈
void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	//首先检查是不是需要扩容
	if (ps->top == ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDataType* tmp = (STDataType*)realloc(ps->a,sizeof(STDataType) * newCapacity);
		if (tmp == NULL)
		{
			printf("realloc fail");
			exit(-1);
		}
		ps->capacity = newCapacity;
		ps->a = tmp;
	}
	ps->a[ps->top] = x;
	ps->top++;
}
//出栈
void StackPop(ST* ps)
{
	assert(ps);
	//有元素才能出栈
	assert(ps->top > 0);
	//只需要ps--就可以了
	ps->top--;

}
//获取栈中有效元素个数
int StackSize(ST* ps)
{
	assert(ps);
	return ps->top;
}
//获取栈顶元素
STDataType StackTop(ST* ps)
{
	assert(ps);
	return ps->a[ps->top-1];
}
//检测栈是否为空
bool StackEmpty(ST* ps)
{				
	assert(ps);
	return ps->top == 0;
}
//销毁
void StackDestory(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;//ps->a 不用了 所以置空就可以了
	ps->capacity = ps->top = 0;
}





//匿名结构体的使用 可以利用typedef!
typedef struct {
    ST pushst;
    ST popst;
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));
    //初始化两个栈
    StackInit(&obj->pushst);
    StackInit(&obj->popst);
    return obj;
}

void myQueuePush(MyQueue* obj, int x) {
    //入队统一在push栈中入数据
    StackPush(&obj->pushst,x);
}

int myQueuePop(MyQueue* obj) {
    //出栈 是对pop进行的
    //如果popst为空 那么首先把pushst里的数据导入到popst
    if(StackEmpty(&obj->popst))
    {
         while(!StackEmpty(&obj->pushst))
         {
             StackPush(&obj->popst,StackTop(&obj->pushst));
             StackPop(&obj->pushst);
         }
    }
    //需要记录队尾 并返回
    int qtail=StackTop(&obj->popst);
    //出队
    StackPop(&obj->popst);
    //返回队尾元素
    return qtail;
    
   
}

int myQueuePeek(MyQueue* obj) {
    //队列的头相当于 popst的栈顶
    //首先判断是不是空 如果是空 导入到popst
    if(StackEmpty(&obj->popst))
    {
        while(!StackEmpty(&obj->pushst))
         {
             StackPush(&obj->popst,StackTop(&obj->pushst));
             StackPop(&obj->pushst);
         }
    }

    return StackTop(&obj->popst);
}

bool myQueueEmpty(MyQueue* obj) {
    //什么时候为空呢?
    //显然 如果两个栈都为空 说明队列为空
    return StackEmpty(&obj->pushst) && StackEmpty(&obj->popst);
}

void myQueueFree(MyQueue* obj) {
    //首先释放两个栈
    //然后释放MyQueue
    StackDestory(&obj->pushst);
    StackDestory(&obj->popst);
    free(obj);
}

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

✨感谢阅读~ ✨
❤️码字不易,给个赞吧~❤️

在这里插入图片描述

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

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

相关文章

STM32标准库学习之寄存器方法点亮LED灯

STM32C8T6最小系统开发板,点亮PC13引脚的LED灯 1.使能PC13引脚的定时器 PC13引脚为GPIOC组的第13个端口,GPIO的时钟使能定时器为RCC_APB2ENR,这是可以从手册中得出的,如下图所示 从下图可以得出,若要使能GPIOC端口&a…

探索 Echarts 绘图:数据可视化的奇妙之旅

目录 一、Echarts 初印象 二、搭建 Echarts 绘图环境 三、绘制第一个图表:柱状图的诞生 四、图表的美化与定制:让数据更具吸引力 1. 主题切换:一键变换风格 2. 颜色调整:色彩搭配的艺术 3. 标签与提示框:丰富信…

泷羽sec-burp(6)暴力破解与验证码识别绕过(下,验证码识别绕过0) 学习笔记

声明! 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关&a…

docker快速实现ELK的安装和使用

目录 一、ELK功能原理 二、项目功能展示​ 三、日志查询展示​ 四、ELK安装步骤 1、创建elasticsearch、kibana、filebeat相关data、log、conf目录 2、进入/usr/local/elk目录,并创建一个docker网络 3、启动 elasticsearch容器 4、运行kibana容器 5、启动f…

onnx算子的注册详解及案例 (完整版)

文章目录 1. 介绍1.1 导出onnx不成功1.2 分析和解决方案2. 案例2.1 Asinh算子注册2.1.1 导出onnx2.1.2 算子注册2.2 自定义算子的注册2.1 直接导出自定义算子2.2 自定义算子的注册并导出2.3 导出带deformable conv 的onnx2.3.1 直接导出deformable conv2.3.2 注册并导出deforma…

数据结构_拓扑排序

拓扑排序 (所有点按照先后顺序排序) 1.先找到入度为0的点,记录之后,删除这个点和它的出边; 2.若有两个可选,随便选择一个 例 a的入度为0,选a [a] 随便选一个 [a,e] 再找入度为0的点 再选c 最后选d 拓…

在线项目管理工具内网怎么用

随着企业规模的扩大和项目管理复杂性的增加,许多公司已经开始使用在线项目管理工具来提高协作效率和项目透明度。然而,在企业内部网络环境下如何有效地使用这些工具,尤其是针对安全性、权限管理以及高效团队协作的问题,仍然是许多…

《自制编译器》--青木峰郎 -读书笔记 编译hello

在该书刚开始编译hello.cb时就遇到了问题。 本人用的是wsl,环境如下, 由于是64位,因此根据书中的提示,从git上下载了64位的cb编译器 cbc-64bit 问题一: 通过如下命令编译时,总是报错。 cbc -Wa,"--32" -Wl,"-…

使用C#和OPenCV实现圆形检测

文章目录 霍夫变换使用 OpenCV 和 C# 实现圆形检测 霍夫变换 在计算机视觉中,圆形检测是一个常见且有用的任务,特别是在物体识别、图像分析和图形处理等领域。OpenCV 是一个强大的开源计算机视觉库,它提供了许多工具来实现不同的图像处理功能…

数字图像处理(23):YUV444与YUV422

(1)在YUV颜色空间中,“Y”表示灰度,可以体现人眼对亮度的敏感程度,如果没有U和V信息,只有Y信息,图像仍然可以显示出来,只不过是灰色的;“U”和“V”表示色度,…

HQChart使用教程30-K线图如何对接第3方数据42-DRAWTEXTREL,DRAWTEXTABS数据结构

HQChart使用教程30-K线图如何对接第3方数据42-DRAWTEXTREL,DRAWTEXTABS数据结构 效果图DRAWTEXTREL示例数据结构说明nametypecolorDrawVAlignDrawAlignDrawDrawTypeDrawDataFont DRAWTEXTABS示例数据结构说明nametypecolorDrawVAlignDrawAlignDrawDrawTypeDrawDataFont 效果图 …

elasticsearch 使用Painless脚本

文章目录 1. 创建索引2. 插入模拟数据Painless 脚本的基本特点:Painless 脚本的常见用途1. 脚本查询和过滤示例:基于脚本的查询 2. 脚本字段示例:脚本字段 3. 聚合中的脚本示例:脚本聚合 4. 文档更新中的脚本示例:文档…

PHP搭建环境

一、安装apache 1、获取Apache安装软件 2、双击安装即可:指定对应的路径:E:server/apache 3、选择安装模式:使用自定义模式 4、选择安装位置 二、Apache的目录结构说明 三、Httpd.exe的详细应用 1、服务器进程:运行之后才能够工作

spring cloud contract http实例

微服务很多时,服务之前相互调用,接口参数的一致性要变得很难维护。 spring cloud contract 提供了测试接口一致性的方法。 一 项目配置 plugins {id "groovy"id "org.springframework.cloud.contract" version "4.0.5"i…

【GIS教程】使用GDAL-Python将tif转为COG并在ArcGIS Js前端加载-附完整代码

目录 一、数据格式 二、COG特点 三、使用GDAL生成COG格式的数据 四、使用ArcGIS Maps SDK for JavaScript加载COG格式数据 一、数据格式 COG(Cloud optimized GeoTIFF)是一种GeoTiff格式的数据。托管在 HTTP 文件服务器上,可以代替geose…

python数据分析之爬虫基础:解析

目录 1、xpath 1.1、xpath的安装以及lxml的安装 1.2、xpath的基本使用 1.3、xpath基本语法 2、JsonPath 2.1、jsonpath的安装 2.2、jsonpath的使用 2.3、jsonpath的基础语法 3、BeautifulSoup 3.1、bs4安装及创建 3.2、beautifulsoup的使用 3.3、beautifulsoup基本语…

【Python网络爬虫笔记】10- os库存储爬取数据

os库的作用 操作系统交互:os库提供了一种使用Python与操作系统进行交互的方式。使用os库来创建用于存储爬取数据的文件夹,或者获取当前工作目录的路径,以便将爬取的数据存储在合适的位置。环境变量操作:可以读取和设置环境变量。在…

TCP 为什么是 3 次握手 4 次挥手?

前言: TCP 的 3 次握手 4 次挥手是一个非常经典的问题,相信各位从事 Java 的朋友在职业生涯中没少被问到这个问题,本篇我们就展开分析一下 TCP 为什么是 3 次握手 4 次挥手。 TCP 协议 要搞清楚 TCP 为什么是 3 次握手 4 次挥手我们需要先…

智能客户服务:科技赋能下的新体验

在当今这个数字化时代,客户服务已经不仅仅是简单的售后服务,它已竞争的关键要素之一。随着人工智能、大数据、云计算等技术的飞速发展,智能客户服务正逐步改变着传统的服务模式,为企业和消费者带来了前所未有的新体验。 一、智能客…

C++ 内存管理和模板与STL

此篇目是之后各种C库的基础 目录 内存管理 内存分布 内存管理方式 new和delete operator new 与 operator delete函数 实现原理 定位new表达式(placement-new) 模板基础 泛型编程 模板 函数模板 类模板 STL 组成部分 内存管理 内存分布 int globalVar 1; //全局变量 静…