数据结构:栈和队列与栈实现队列(C语言版)

目录

前言

1.栈

1.1 栈的概念及结构

1.2 栈的底层数据结构选择

1.2 数据结构设计代码(栈的实现)

1.3 接口函数实现代码

(1)初始化栈

(2)销毁栈

(3)压栈

(4)出栈

(5)获取栈顶元素

(6)获取栈中有效元素的个数

(7)检测栈是否为空

1.4 测试函数

2. 队列

2.1 队列概念及结构

2.2 队列的底层数据结构的选择

2.2 数据结构设计代码(队列的实现)

2.3 接口函数

(1)初始化队列

(2)销毁队列

(3)队尾入队列

(4)队头出队列

(5)获取队列头部元素

(6)获取队列尾部元素

(7)获取队列中有效元素个数

(8)检测队列是否为空

2.4 测试函数

3. 栈和队列的源代码

3.1 栈

(1)Stack.h

(2)Stack.c

(3)STtest.c

3.2 队列

(1)Queue.h

(2)Queue.c

(3)Qtest.c

总结


前言

这篇文章是关于栈和队列的C语言实现,干货满满,大家可以边看边手写代码,最后附上栈和队列的参考代码。


1.栈

1.1 栈的概念及结构

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

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶
出栈:栈的删除操作叫做出栈。出数据也在栈顶

这个数据结构可以理解为炸串。在最开始,插入丸子时,要插到这根签的最底部,就是入栈。开始吃的时候,一般从最上面的丸子入手,就是出栈

 

1.2 栈的底层数据结构选择

我们学过顺序表和链表两种数据结构,用那种会更好呢?

  • 相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。不用挪动数据,删除操作也很简单。
  • 而链表如果要入栈,就是链表的尾插,我们需要找到链表的尾结点,效率低。出栈也是一样。

1.2 数据结构设计代码(栈的实现)

在用C语言实现栈各种接口函数,需要创建三个文件,分别是STtest.c,Stack.c和Stack.h。

  • STtest.c文件用来测试接口函数是否能成功。
  • Stack.c文件里面放的是各种接口函数实现的代码
  • Stack.h文件放置各种头文件的声明,栈数据结构的设计和接口函数的声明。下面的代码就是放在此文件中。
typedef int STDataType;
// 下面是定长的静态栈的结构,实际中一般不实用,所以我们主要实现下面的支持动态增长的栈
typedef int STDataType;
#define N 10
typedef struct Stack
{STDataType _a[N];int _top; // 栈顶
}Stack;// 支持动态增长的栈
typedef struct Stack
{STDataType* a;int top;      //栈顶int capacity; //容量
}ST;//初始化栈
void StackInit(ST* ps);
//销毁栈
void StackDestroy(ST* ps);
//压栈
void StackPush(ST* ps, STDataType x);
//出栈
void StackPop(ST* ps);
//获取栈顶元素
STDataType StackTop(ST* ps);
//获取栈中有效元素个数
int StackSize(ST* ps);
//检测栈是否为空,为空返回true
bool StackEmpty(ST* ps);

1.3 接口函数实现代码

(1)初始化栈

初始化栈一开始要断言,断言来判断ps指针是否为空,如果为空会直接终止程序并给出提示,方便之后的调试,之后的断言不再赘述。指针指向空,内部整型数据赋值为0。但是top得注意,top其实也是个下标。看下面的注释,top可以有两种赋值方式,只是表示不同意思。

void StackInit(ST* ps)
{assert(ps);ps->a = NULL;ps->top = 0;//表示指向栈顶的下一个元素//ps->top = -1 ///表示指向栈顶元素ps->capacity = 0;
}

(2)销毁栈

因为我们是以数组为基础,是动态开辟的连续空间,直接释放掉ps中的数组指针,并要置为空。

void StackDestroy(ST* ps)
{assert(ps);free(ps->a);ps->a = NULL;//易错ps->top = ps->capacity = 0;
}

(3)压栈

栈的压栈操作跟顺序表的尾插类似,先要检查内部空间容量是否足够,一开始给四个该数据结构的空间,之后的按两倍来扩容。最后就是插入数据,栈顶减一。

void StackPush(ST* ps, STDataType x)
{assert(ps);if (ps->top == ps->capacity){int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;STDataType* tmp = realloc(ps->a, sizeof(STDataType) * newCapacity);if (tmp == NULL){printf("realloc fail\n");exit(-1);}ps->a = tmp;ps->capacity = newCapacity;}ps->a[ps->top] = x;ps->top++;
}

(4)出栈

这次不仅要判断ps是否不为空指针,还要判断栈内是否有元素,这样才可以删除元素,让栈顶减一即可。

void StackPop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));ps->top--;
}

(5)获取栈顶元素

这里的判断跟上个接口函数一样,只有栈内有元素,才能取栈顶元素。

STDataType StackTop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));return ps->a[ps->top - 1];
}

(6)获取栈中有效元素的个数

此时的top表示的是栈顶的下一个元素的下标,刚好就是元素个数,直接返回栈顶top

int StackSize(ST* ps)
{assert(ps);return ps->top;
}

(7)检测栈是否为空

很多人会写个if语句判断,其实可以直接像下面一样写,ps->top == 0变成一个判断语句,如果为真返回一个部位0的数,如果为假返回0。

bool StackEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}

1.4 测试函数

我们写两个测试函数,第一个测试函数,是出栈和入栈的操作,可以调试查看。第二个测试函数是栈的数据打印,需要使用StackTop获取栈顶元素,然后将打印的数据出栈。

void TestStack1()
{ST st;StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);StackPop(&st);StackPop(&st);StackPop(&st);StackPop(&st);StackPop(&st);StackDestroy(&st);
}void TestStack2()
{ST st;StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);while (!StackEmpty(&st)){printf("%d ", StackTop(&st));StackPop(&st);}StackDestroy(&st);
}int main()
{TestStack1();TestStack2();return 0;
}

输出结果:

2. 队列

2.1 队列概念及结构

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

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

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

 这个数据结构可以理解为在银行取号,先取号的人,就是入队列。然后先取到号的人,就先去窗口处理业务,这就是出队列。

2.2 队列的底层数据结构的选择

跟栈一样,队列也可以用顺序表和链表来实现,那哪一个更好呢?

  • 相较于数组,使用链表更优一些。队列的入队和出队,分别是链表的尾插和头删,不过我们会创建两个指针指向头结点和尾结点,所以不会有时间的消耗。
  • 而数组在头部插入和删除数据,都要挪动数据,效率较低。

链表的数据结构存储的是一个数据变量,和指向下一个结点的指针变量。我们入队列和出队列分别在队尾和队头,所以我们在队列的数据结构定义两个链表的指针变量head和tail,表示队头和队尾

2.2 数据结构设计代码(队列的实现)

跟栈的实现一样,首先要创建三个文件Qtest.c,Queue.c和Queue.h。

  • Qtest.c文件用来测试接口函数是否能成功。
  • Queue.c文件里面放的是各种接口函数实现的代码
  • Queue.h文件放置各种头文件的声明,栈数据结构的设计和接口函数的声明。下面的代码就是放在此文件中。
// 链式结构:表示队列
typedef int QDataType;
typedef struct QueueNode
{struct QueueNode* next;QDataType data;
}QueueNode;// 队列的结构
typedef struct Queue
{QueueNode* head;QueueNode* tail;
}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);
//检测队列是否为空,如果为空返回true
bool QueueEmpty(Queue* pq);

2.3 接口函数

(1)初始化队列

队列初始化,只需要将队头链表指针和队尾链表指针置为空指针就好。

void QueueInit(Queue* pq)
{assert(pq);pq->head = NULL;pq->tail = NULL;
}

(2)销毁队列

因为是以链表为基础,需要用while循环释放掉每一个动态开辟的结点。

void QueueDestroy(Queue* pq)
{assert(pq);QueueNode* cur = pq->head;while (cur != NULL){QueueNode* next = cur->next;free(cur);cur = next;}pq->head = pq->tail = NULL;
}

(3)队尾入队列

队尾入队列就是链表的尾插,但是我们有tail指针,直接在tail后面插入就好。不过需要分是否为空队列两种情况,如果是空队列,head和tail指针都指向新结点,如果不是空队列,在tail之后插入。

void QueuePush(Queue* pq, QDataType x)
{assert(pq);QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));if (newnode == NULL){perror("Queue malloc fail");return;}newnode->data = x;newnode->next = NULL;if (pq->head == NULL){pq->head = pq->tail = newnode;}else{pq->tail->next = newnode;pq->tail = newnode;}
}

(4)队头出队列

在操作之前,我们需要判断队列是否有元素。然后在释放第一个结点,改变指针指向。

void QueuePop(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));QueueNode* next = pq->head->next;free(pq->head);pq->head = next;
}

(5)获取队列头部元素

QDataType QueueFront(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->head->data;
}

(6)获取队列尾部元素

QDataType QueueBack(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->tail->data;
}

(7)获取队列中有效元素个数

这需要一个计数变量。

int QueueSize(Queue* pq)
{assert(pq);int n = 0;QueueNode* cur = pq->head;while (cur){n++;cur = cur->next;}return n;
}

(8)检测队列是否为空

跟栈判空相同。

bool QueueEmpty(Queue* pq)
{assert(pq);return pq->head == NULL;
}

2.4 测试函数

写两个测试函数,第一是入队列和出队列的操作,可以一步一步调试看情况。第二个测试函数,是打印队列里的数据,现获取队头的数据,然后再出队。

void TestQueue1()
{Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);QueuePop(&q);QueuePop(&q);QueuePop(&q);QueuePop(&q);printf("%d\n", QueueBack(&q));QueueDestroy(&q);
}void TestQueue2()
{Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);while (!QueueEmpty(&q)){QDataType front = QueueFront(&q);printf("%d ", front);QueuePop(&q);}printf("\n");
}int main()
{TestQueue1();TestQueue2();return 0;
}

输出的结果:

3. 栈和队列的源代码

3.1 栈

(1)Stack.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>typedef int STDataType;下面是定长的静态栈的结构,实际中一般不实用,所以我们主要实现下面的支持动态增长的栈
//typedef int STDataType;
//#define N 10
//typedef struct Stack
//{
//	STDataType _a[N];
//	int _top; // 栈顶
//}Stack;// 支持动态增长的栈
typedef struct Stack
{STDataType* a;int top;      //栈顶int capacity; //容量
}ST;
//初始化栈
void StackInit(ST* ps);
//销毁栈
void StackDestroy(ST* ps);
//压栈
void StackPush(ST* ps, STDataType x);
//出栈
void StackPop(ST* ps);
//获取栈顶元素
STDataType StackTop(ST* ps);
//获取栈中有效元素个数
int StackSize(ST* ps);
//检测栈是否为空,为空返回true
bool StackEmpty(ST* ps);

(2)Stack.c

#include "Stack.h"void StackInit(ST* ps)
{assert(ps);ps->a = NULL;ps->top = 0;//ps->top = -1ps->capacity = 0;
}void StackDestroy(ST* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->top = ps->capacity = 0;
}void StackPush(ST* ps, STDataType x)
{assert(ps);if (ps->top == ps->capacity){int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;STDataType* tmp = realloc(ps->a, sizeof(STDataType) * newCapacity);if (tmp == NULL){printf("realloc fail\n");exit(-1);}ps->a = tmp;ps->capacity = newCapacity;}ps->a[ps->top] = x;ps->top++;
}void StackPop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));ps->top--;
}STDataType StackTop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));return ps->a[ps->top - 1];
}int StackSize(ST* ps)
{assert(ps);return ps->top;
}bool StackEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}

(3)STtest.c

#include "Stack.h"void TestStack1()
{ST st;StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);StackPop(&st);StackPop(&st);StackPop(&st);StackPop(&st);StackPop(&st);StackDestroy(&st);
}void TestStack2()
{ST st;StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);//printf("%d ", StackTop(&st));//StackPop(&st);//printf("%d ", StackTop(&st));//StackPop(&st);//StackPush(&st, 5);//StackPush(&st, 6);while (!StackEmpty(&st)){printf("%d ", StackTop(&st));StackPop(&st);}StackDestroy(&st);
}int main()
{TestStack1();//TestStack2();return 0;
}

3.2 队列

(1)Queue.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>// 链式结构:表示队列
typedef int QDataType;
typedef struct QueueNode
{struct QueueNode* next;QDataType data;
}QueueNode;// 队列的结构
typedef struct Queue
{QueueNode* head;QueueNode* tail;
}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);
//检测队列是否为空,如果为空返回true
bool QueueEmpty(Queue* pq);

(2)Queue.c

#include "Queue.h"void QueueInit(Queue* pq)
{assert(pq);pq->head = NULL;pq->tail = NULL;
}void QueueDestroy(Queue* pq)
{assert(pq);QueueNode* cur = pq->head;while (cur != NULL){QueueNode* next = cur->next;free(cur);cur = next;}pq->head = pq->tail = NULL;
}void QueuePush(Queue* pq, QDataType x)
{assert(pq);QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));if (newnode == NULL){perror("Queue malloc fail");return;}newnode->data = x;newnode->next = NULL;if (pq->head == NULL){pq->head = pq->tail = newnode;}else{pq->tail->next = newnode;pq->tail = newnode;}
}void QueuePop(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));QueueNode* next = pq->head->next;free(pq->head);pq->head = next;
}QDataType QueueFront(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->head->data;
}QDataType QueueBack(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->tail->data;
}int QueueSize(Queue* pq)
{assert(pq);int n = 0;QueueNode* cur = pq->head;while (cur){n++;cur = cur->next;}return n;
}bool QueueEmpty(Queue* pq)
{assert(pq);return pq->head == NULL;
}

(3)Qtest.c

void TestQueue1()
{Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);QueuePop(&q);QueuePop(&q);QueuePop(&q);QueuePop(&q);printf("%d\n", QueueBack(&q));QueueDestroy(&q);
}void TestQueue2()
{Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);while (!QueueEmpty(&q)){QDataType front = QueueFront(&q);printf("%d ", front);QueuePop(&q);}printf("\n");
}int main()
{//TestQueue1();TestQueue2();return 0;
}

 


总结

栈和队列的实现其实相较于链表的实现简单一些,是因为其结构的特殊要求。之后会出一篇关于栈和队列的OJ题目。多多重复,百炼成钢!

创作不易,希望这篇文章能给你带来启发和帮助,如果喜欢这篇文章,请留下你的三连,你的支持的我最大的动力!!!

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

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

相关文章

Unity(第九部)物体类

拿到物体的某些数据 using System.Collections; using System.Collections.Generic; using UnityEngine;public class game : MonoBehaviour {// Start is called before the first frame updatevoid Start(){//拿到当前脚本所挂载的游戏物体//GameObject go this.gameObject;…

踩坑wow.js 和animate.css一起使用没有效果

踩坑wow.js 和animate.css一起使用没有效果 问题及解决方法一、电脑系统配置问题二、版本问题 问题及解决方法 一、电脑系统配置问题 在系统属性里面把窗口内的动画和元素勾选 二、版本问题 使用wow加animate4.4.1也就是最新本&#xff0c;打开网页没有任何动画效果 但是把…

CSS——PostCSS简介

文章目录 PostCSS是什么postCSS的优点补充&#xff1a;polyfill补充&#xff1a;Stylelint PostCSS架构概述工作流程PostCSS解析方法PostCSS解析流程 PostCSS插件插件的使用控制类插件包类插件未来的CSS语法相关插件后备措施相关插件语言扩展相关插件颜色相关组件图片和字体相关…

45、上海大学:轻量级多特征神经网络M-FANet,用于MI-BCI解码

本文由上海大学机电工程与自动化学院于2024.1.9日发表于《IEEE Transactions on Neural Systems and Rehabilitation Engineering》(SCI中科院分区二区&#xff0c;IF&#xff1a;4.9) 论文链接&#xff1a;M-FANet: Multi-Feature Attention Convolutional Neural Network fo…

数据结构--二叉排序树(Binary Search Tree,简称BST)

这里写自定义目录标题 二叉排序树二叉排序树与排序数组没有排序数组&#xff0c;链式存储链表的对比二叉排序树概念对于搜索操作&#xff0c;对于插入操作&#xff0c;对于删除操作&#xff0c; 分析删除节点代码运行结果 二叉排序树 二叉排序树与排序数组没有排序数组&#x…

【React源码 - 调度任务循环EventLoop】

我们知道在React中有4个核心包、2个关键循环。而React正是在这4个核心包中运行&#xff0c;从输入到输出渲染到web端&#xff0c;主要流程可简单分为一下4步&#xff1a;如下图&#xff0c;本文主要是介绍两大循环中的任务调度循环。 4个核心包&#xff1a; react&#xff1a;…

SpringMVC了解

1.springMVC概述 Spring MVC&#xff08;Model-View-Controller&#xff09;是基于 Java 的 Web 应用程序框架&#xff0c;用于开发 Web 应用程序。它通过将应用程序分为模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;和控制器&#xff08;Controller&a…

SpringMVC 学习(八)之文件上传与下载

目录 1 文件上传 2 文件下载 1 文件上传 SpringMVC 对文件的上传做了很好的封装&#xff0c;提供了两种解析器。 CommonsMultipartResolver&#xff1a;兼容性较好&#xff0c;可以兼容 Servlet3.0 之前的版本&#xff0c;但是它依赖了 commons-fileupload …

kubectl 命令行管理K8S(上)

目录 陈述式资源管理方式 介绍 命令 项目的生命周期 创建 kubectl create命令 发布 kubectl expose命令 更新 kubectl set 回滚 kubectl rollout 删除 kubectl delete 应用发布策略 金丝雀发布 陈述式资源管理方式 介绍 1.kubernetes 集群管理集群资源…

python 基础知识点(蓝桥杯python科目个人复习计划53)

今日复习内容&#xff1a;做题 例题1&#xff1a;最大的卡牌价值 问题描述&#xff1a; 给定n副卡牌&#xff0c;每张卡牌具有正反面&#xff0c;正面朝上数字为ai&#xff0c;背面朝上数字为bi。一副卡牌的价值为正面朝上数字之和&#xff0c;一开始所有卡牌都是正面朝上的…

【已解决】用ArcGIS处理过的数据在QGIS中打开发生偏移怎么办?| 数据在ArcGIS中打开位置正常,在QGIS中偏移

1. 问题描述 栅格或者矢量数据用ArcGIS打开时位置正确&#xff08;可以和其他数据对应上&#xff09;。但是用QGIS打开后发现位置不对 2. 问题的原因 因为该数据用了ArcGIS自定义的坐标系&#xff0c;QGIS不支持&#xff0c;识别有误。因此在数据QGIS中的坐标系参数有误&a…

HTTP 的 multipart 类型

上一篇文章讲到 http 的 MIME 类型 http MIME 类型 里有一个 multipart 多部分对象集合类型&#xff0c;这个类型 http 指南里有讲到&#xff1a;MIME 中的 multipart&#xff08;多部分&#xff09;电子邮件报文中包含多个报文&#xff0c;它们合在一起作为单一的复杂报文发送…

【生态适配】亚信安慧AntDB数据库与FT-2000+/64处理器完成兼容互认

日前&#xff0c;亚信安慧AntDB数据库完成了与FT-2000/64处理器的兼容互认。经湖南亚信安慧科技有限公司&#xff08;简称“亚信安慧”&#xff09;与飞腾信息技术有限公司&#xff08;简称“飞腾公司”&#xff09;的严格测试&#xff0c;亚信安慧AntDB数据库V6.2在FT-2000/64…

《大模型时代-ChatGPT开启通用人工智能浪潮》精华摘抄

原书很长&#xff0c;有19.3w字&#xff0c;本文尝试浓缩一下其中的精华。 知识点 GPT相关 谷歌发布LaMDA、BERT和PaLM-E&#xff0c;PaLM 2 Facebook的母公司Meta推出LLaMA&#xff0c;并在博客上免费公开LLM&#xff1a;OPT-175B。 在GPT中&#xff0c;P代表经过预训练(…

一看就会:使用nvm实现多个版本的node自由切换

一、介绍 使用nvm可以方便的在同一台设备上进行多个node版本之间切换&#xff0c;解决不同的项目所使用的node版本不一样的问题 二、安装nvm 如果已安装node环境先卸载后再安装nvm&#xff0c;防止出现不确定错误 1、卸载node环境&#xff0c;并清除node环境变量配置 通过…

【README 小技巧】 展示gitee中开源项目start

【README 小技巧】 展示gitee中开源项目start <a target"_blank" hrefhttps://gitee.com/wujiawei1207537021/wu-framework-parent><img srchttps://gitee.com/wujiawei1207537021/wu-framework-parent/badge/star.svg altGitee star/></a>

我在使用 Copilot 时遇到了许可证验证错误。

如果使用的是 Copilot&#xff0c;并收到以下错误消息&#xff0c;请按以下步骤进行操作&#xff1a; We encountered a problem validating your Copilot license. For more information, see https://aka.ms/copilotlicensecheck 请确保使用的是正确的帐户 请确保已使用具…

Flink动态分区裁剪

1 原理 1.1 静态分区裁剪与动态分区裁剪 静态分区裁剪的原理跟谓词下推是一致的&#xff0c;只是适用的是分区表&#xff0c;通过将where条件中的分区条件下推到数据源达到减少分区扫描的目的   动态分区裁剪应用于Join场景&#xff0c;这种场景下&#xff0c;分区条件在joi…

kafka平滑升级过程指导

一、前言 Apache Kafka作为常用的开源分布式流媒体平台&#xff0c;可以实时发布、订阅、存储和处理数据流,多用于作为消息队列获取实时数据&#xff0c;构建对数据流的变化进行实时反应的应用程序&#xff0c;已被数千家公司用于高性能数据管道、流分析、数据集成和任务关键型…

算法day01_ 27. 移除元素、977.有序数组的平方

推荐阅读 从零开始学数组&#xff1a;深入浅出&#xff0c;带你掌握核心要点 初探二分法 再探二分法 系统的纪录一下刷算法的过程&#xff0c;之前一直断断续续的刷题&#xff0c;半途而废&#xff0c;现在重新开始。话不多说&#xff0c;开冲&#xff01; 27.移除元素 题目 给…