数据结构学习之路--玩转队列的内核知识(附C源码)

   嗨嗨大家~我又来啦!今天为大家带来的是与队列相关的知识。我们马上进入知识的海洋~


目录

前言

一、队列 

1 队列的概念 

2 队列的实现 

2.1 队列的定义 

2.2 队列的初始化 

2.3 队列的判空 

2.4 入队 

2.5 出队 

2.6 取队头元素 

2.7 取队尾元素 

2.8 取有效元素个数(队列大小)

2.9 队列的销毁 

二、源代码 

三、栈与队列的经典题 

 1 有效的括号

2 用队列实现栈 

3 用栈实现队列 

4 设计循环队列 


前言

   说起队列,不妨来想象一下,在我们的生活中总是存在一种现象:排队。它就可以看作是队列,比如:我们在排队打饭的时候,先排队的人先打饭,打完饭后便出队了,也就是说最先排队的人最先出队,最后排队的人最后出队。有了此依据,我们来对队列作出详细讲解:

一、队列 

首先根据下图直观的了解队列的相关内容:

1 队列的概念 

   队列是一种特殊的线性表,特性是先进先出,即First In First Out(FIFO)。最先加入的元素最先取出,最后加入的元素最后取出。队列有头部和尾部,队列头部称为队头(首),队列尾部称为队尾,队列内的元素从队头到队尾的顺序符合加入队列的顺序。它只允许在一端进行插入(入队),在另一端删除的线性表(出队)。文字描述未免过于死板,为了更好的帮助大家理解,附以下图解:

左边为队头,右边为队尾。将数字 1  到 7 依次入队之后,此时队首元素是 1 ,队尾元素是 7 ,第一个出队的元素是 1 。 

2 队列的实现 

队列一般需要这样几个功能:

  • 初始化队列
  • 判断队列是否为空
  • 入队
  • 出队
  • 取队头元素
  • 取队尾元素
  • 取有效元素个数(大小)
  • 队列的销毁

2.1 队列的定义 

//定义
typedef int QDataType;//链式队列结点
typedef struct QueueNode
{struct QueueNode* next;QDataType data;
}QNode;//链式队列
typedef struct Queue
{QNode* head;//队列的头QNode* tail;//队列的尾
}Queue;

2.2 队列的初始化 

//初始化
void QueueInit(Queue* pq)
{//判空assert(pq);//不带哨兵位(即不带头结点)pq->head = pq->tail = NULL;
}

这里实现的是不带头结点的链式队列,初始时 front 和 rear 都指向NULL。 

2.3 队列的判空 

//判空
bool QueueEmpty(Queue* pq)
{//判空assert(pq);//看队头元素是否为NULLreturn pq->head == NULL;
}

判断队列是否为空,仅需要看队头元素是否为NULL。 

2.4 入队 

//入队
void QueuePush(Queue* pq, QDataType x)
{//判空assert(pq);//创建新结点newnodeQNode* newnode = (QNode*)malloc(sizeof(QNode));//判空if (newnode == NULL){perror("malloc fail\n");exit(-1);}newnode->data = x;newnode->next = NULL;//链表为空if (pq->tail == NULL){//在空队列中插入第一个元素//修改队头队尾指针pq->head = pq->tail = newnode;}else{//链表不为空pq->tail->next = newnode;//新结点插入到tail结点之后pq->tail = newnode;//修改tail指针}
}

在入队之前,需要调用 malloc 函数开辟一个新结点 newnode。对于不带头结点的情况,第一个元素入队时要特殊处理。由于一开始这两个指针都是指向NULL的,因此插入第一个元素时对这两个指针都要进行修改。 

2.5 出队 

//出队
void QueuePop(Queue* pq)
{//判空assert(pq);//判断队列是否为空assert(!QueueEmpty(pq));//只含一个结点if (pq->head->next == NULL){free(pq->head);//释放最后一个结点pq->head = pq->tail = NULL;//将队头与队尾指针都置空}else//含多个结点{QNode* next = pq->head->next;//next为队头结点的下一个结点free(pq->head);//释放队头结点pq->head = next;//修改头指针}
}

在出队之前,首先需要判断队列是否为空,若队列为空,则无法进行出队操作。当只剩下最后一个元素未出队时需特殊处理。首先需要调用 free函数释放首元素,然后将队头指针与队尾指针都置为 NULL。当还剩多个元素时,首先找到队头结点的下一个结点,然后调用 free函数释放掉队头结点,最后将 队头指针head 指向 next,更新队头元素。 

2.6 取队头元素 

//取队头元素
QDataType QueueFront(Queue* pq)
{//判空assert(pq);//判断队列是否为空assert(!QueueEmpty(pq));//取队头元素return pq->head->data;
}

在取队头元素之前,首选需要调用函数 QueueEmpty(pq) 判断队列是否为空,若为空,则无法取队头元素。若队列不为空,则取队头元素。 

2.7 取队尾元素 

//取队尾元素
QDataType QueueBack(Queue* pq)
{assert(pq);//判断队列是否为空assert(!QueueEmpty(pq));//取队尾元素return pq->tail->data;
}

在取队尾元素之前,首选需要调用函数 QueueEmpty(pq) 判断队列是否为空,若为空,则无法取队尾元素。若队列不为空,则取队尾元素。 

2.8 取有效元素个数(队列大小)

//取有效元素个数(队列大小)
int QueueSize(Queue* pq)
{//判空assert(pq);//设置指针变量cur,用于遍历队列QNode* cur = pq->head;int size = 0;//遍历队列while (cur){++size;cur = cur->next;}return size;
}

在求队列的元素个数时,首先设置指针变量 cur,并使其指向队头元素,然后设置一个变量 size,用于统计元素个数。让指针变量 cur进入 while循环遍历整个队列,每遍历一个元素, size就自增1,直到 cur走到队尾,则跳出循环,并返回 size大小。 

2.9 队列的销毁 

//销毁
void QueueDestory(Queue* pq)
{//判空assert(pq);//设置指针变量cur,用于遍历队列QNode* cur = pq->head;//遍历队列while (cur){QNode* next = cur->next;free(cur);cur = next;}//将队头指针,队尾指针均置为空pq->head = pq->tail = NULL;
}

首先设置指针变量 cur,并使其指向队头元素,然后让指针变量 cur进入 while循环遍历整个队列,每遍历一个元素,就将其前一个元素释放掉,直到 cur走到队尾,则跳出循环。在销毁整个链表之后要将队头指针与队尾指针均置为 NULL。 

二、源代码 

Queue.h#pragma once#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>typedef int QDataType;//链式队列结点
typedef struct QueueNode
{struct QueueNode* next;QDataType data;
}QNode;//链式队列
typedef struct Queue
{QNode* head;//队列的头QNode* tail;//队列的尾
}Queue;//初始化
void QueueInit(Queue* pq);//判空
bool QueueEmpty(Queue* pq);//入队
void QueuePush(Queue* pq, QDataType x);//出队
void QueuePop(Queue* pq);//取队头元素
QDataType QueueFront(Queue* pq);//取队尾元素
QDataType QueueBack(Queue* pq);//元素个数(队列大小)
int QueueSize(Queue* pq);//销毁
void QueueDestory(Queue* pq);
Queue.c#include"Queue.h"​​//初始化
void QueueInit(Queue* pq)
{//判空assert(pq);//不带哨兵位(即不带头结点)pq->head = pq->tail = NULL;
}​​//判空
bool QueueEmpty(Queue* pq)
{//判空assert(pq);//看队头元素是否为NULLreturn pq->head == NULL;
}​​//入队
void QueuePush(Queue* pq, QDataType x)
{//判空assert(pq);//创建新结点newnodeQNode* newnode = (QNode*)malloc(sizeof(QNode));//判空if (newnode == NULL){perror("malloc fail\n");exit(-1);}newnode->data = x;newnode->next = NULL;//链表为空if (pq->tail == NULL){//在空队列中插入第一个元素//修改队头队尾指针pq->head = pq->tail = newnode;}else{//链表不为空pq->tail->next = newnode;//新结点插入到tail结点之后pq->tail = newnode;//修改tail指针}
}​​//出队
void QueuePop(Queue* pq)
{//判空assert(pq);//判断队列是否为空assert(!QueueEmpty(pq));//只含一个结点if (pq->head->next == NULL){free(pq->head);//释放最后一个结点pq->head = pq->tail = NULL;//将队头与队尾指针都置空}else//含多个结点{QNode* next = pq->head->next;//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);//设置指针变量cur,用于遍历队列QNode* cur = pq->head;int size = 0;//遍历队列while (cur){++size;cur = cur->next;}return size;
}​​//销毁
void QueueDestory(Queue* pq)
{//判空assert(pq);//设置指针变量cur,用于遍历队列QNode* cur = pq->head;//遍历队列while (cur){QNode* next = cur->next;free(cur);cur = next;}//将队头指针,队尾指针均置为空pq->head = pq->tail = NULL;
}
​
test.c#include"Queue.h"void TestQueue()
{Queue q;//初始化QueueInit(&q);//入队QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);QueuePush(&q, 5);QueuePush(&q, 6);QueuePush(&q, 7);//出队while (!QueueEmpty(&q)){//取对头元素printf("%d ",QueueFront(&q));//出队QueuePop(&q);}printf("\n");//销毁QueueDestory(&q);
}int main()
{test();return 0;
}

三、栈与队列的经典题 

 1 有效的括号

题目描述:

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

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合
  2. 左括号必须以正确的顺序闭合

分析:

   我们可以把左括号依次压入栈中,越往后被压入的左括号越先被弹出栈进行匹配。每出现一个右括号,就”消耗”一个左括号进行匹配检查,这个过程对应出栈操作。扫描一连串括号的过程中若发现下列情况都说明括号序列不合法,终止操作。

注意:

  • 弹出栈的左括号与刚刚遇到要检查的右括号不匹配;
  • 扫描到右括号时发现栈空了(右括号单身);
  • 处理完所有括号后,栈非空(右括号单身)。

代码实现: 

bool isValid(char * s)
{Stack st;StackInit(&st);while(*s){//左括号入栈,右括号找最近的左括号匹配if(*s == '[' || *s == '(' || *s == '{'){StackPush(&st, *s);s++;}else{if(StackEmpty(&st))//只有右括号的情况{StackDestroy(&st);//销毁return false;}char top = StackTop(&st);//不匹配的情况if ( (top == '[' && *s != ']') || (top == '(' && *s != ')')|| (top == '{' && *s != '}') ) {StackDestroy(&st);return false;}else //匹配的情况{StackPop(&st);s++;}}}//如果最后栈内为空才说明是匹配的(防止最后栈内还剩下左括号的情况)bool ret = StackEmpty(&st);StackDestroy(&st);return ret;//特别注意:在return之前需要先把栈销毁掉
}

2 用队列实现栈 

题目描述:

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

实现MyStack类:

  1. void push(int x):将元素x压入栈顶
  2. void pop():移除并返回栈顶元素
  3. int top():返回栈顶元素
  4. boolean empty():如果栈是空的,返回true;否则,返回false

分析:

   队列 queue1保存原始输入数据,队列 queue2作为临时队列缓存数据。当进行 stack_pop操作时,先将 queue1里除最后一个元素外全部出队,并将出队的数据保存在临时队列queue2里,然后保存 queue1的最后一个元素,最后再将 queue2里的全部元素出队,且出队的元素重新放进 queue1里,返回保存的 queue1最后的元素。

代码实现: 

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>typedef int QDataType;//链式队列结点
typedef struct QueueNode
{struct QueueNode* next;QDataType data;
}QNode;//链式队列
typedef struct Queue
{QNode* head;//队列的头QNode* tail;//队列的尾
}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);//判空
bool QueueEmpty(Queue* pq);//元素个数
int QueueSize(Queue* pq);/**********用队列实现栈**********///构造一个包含两个队列的栈
typedef struct
{Queue q1;Queue q2;
}MyStack;//初始化栈
MyStack* myStackCreate()
{//调用malloc为栈开辟内存空间MyStack* obj = (MyStack*)malloc(sizeof(MyStack));//初始化两个队列QueueInit(&obj->q1);QueueInit(&obj->q2);return obj;
}//入栈
void myStackPush(MyStack* obj, int x)
{//判空assert(obj);//往不为空的队列插入元素,若两个队列均为空,插入其中一个即可if (!QueueEmpty(&obj->q1)){QueuePush(&obj->q1,x);}else{QueuePush(&obj->q2,x);}//出栈
int myStackPop(MyStack* obj)
{//判空assert(obj);//假设q1队列为空,q2队列不为空Queue* emptyQ = &obj->q1;Queue* nonEmptyQ = &obj->q2;//若q1队列不为空,则将q2队列设为空,q1队列设为非空if (!QueueEmpty(&obj->q1)){emptyQ = &obj->q2;nonEmptyQ = &obj->q1;}//把非空队列的数据导入到空队列,也就是将非空队列的前n-1个数据导入至另一个空队列while (QueueSize(nonEmptyQ) > 1){QueuePush(emptyQ,QueueFront(nonEmptyQ));//取非空队列对头的数据插入到空队列中去QueuePop(nonEmptyQ);//出队}int top = QueueFront(nonEmptyQ);//取非空队列的队头元素QueuePop(nonEmptyQ);//出队return top;
}//取栈顶元素
int myStackTop(MyStack* obj)
{//判空assert(obj);//若q1队列不为空,则取q1队尾元素if (!QueueEmpty(&obj->q1)){return QueueBack(&obj->q1);}else{//若q2队列不为空,则取q2队尾元素return QueueBack(&obj->q2);}
}//判断栈是否为空
bool myStackEmpty(MyStack* obj)
{//判空assert(obj);//只有当两个队列均为空时,才表示栈为空return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}//销毁栈
void myStackFree(MyStack* obj)
{//判空assert(obj);//销毁队列q1和q2QueueDestory(&obj->q1);QueueDestory(&obj->q2);//释放栈free(obj);
}

3 用栈实现队列 

题目描述:

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push,pop,peek,empty)。

实现MyQueue类:

  1. void push(int x):将元素x推到队列的末尾
  2. int pop():从队列的开头移除并返回元素
  3. int peek():返回队列开头的元素
  4. boolean empty():如果队列为空,返回true;否则,返回false

分析:

   用两个栈实现一个队列,设置其中一个栈 pushst专门入数据,另一个栈 popst专门出数据。若要入队,则进栈 pushst;若要出队,首先看 popst栈是否为空,如果为空,就先把栈 pushst的数据转移过来,然后出队,如果不为空,则直接出栈 popst的数据。

代码实现: 

typedef struct 
{Stack pushST;Stack popST;
} MyQueue;MyQueue* myQueueCreate() 
{MyQueue* q = (MyQueue*)malloc(sizeof(MyQueue));StackInit(&q->pushST);StackInit(&q->popST);return q;
}void myQueuePush(MyQueue* obj, int x)
{//不管栈内有没有数据,只要是入队操作就向Push栈入数据即可StackPush(&obj->pushST, x);
}//获取队头数据
int myQueuePeek(MyQueue* obj) 
{//如果pop栈为空,先把push栈数据导入pop栈if(StackEmpty(&obj->popST)){while(!StackEmpty(&obj->pushST)){StackPush(&obj->popST, StackTop(&obj->pushST));StackPop(&obj->pushST);}}return StackTop(&obj->popST);
}//出队
int myQueuePop(MyQueue* obj) 
{//如果pop栈为空,先把push栈数据导入pop栈/*if(StackEmpty(&obj->popST)){while(!StackEmpty(&obj->pushST)){StackPush(&obj->popST, StackTop(&obj->pushST));StackPop(&obj->pushST);}}*///复用int top = myQueuePeek(obj);//易错点:不能写&obj->popST,因为该传入队列的指针StackPop(&obj->popST);return top;
}bool myQueueEmpty(MyQueue* obj) 
{//push栈和pop栈同时为空,队列才为空return StackEmpty(&obj->pushST) && StackEmpty(&obj->popST);
}void myQueueFree(MyQueue* obj)
{StackDestroy(&obj->pushST);StackDestroy(&obj->popST);free(obj);
}

4 设计循环队列 

 题目描述:

设计你的循环队列实现。循环队列是一种线性数据结构,其操作表现基于FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为"环形缓冲器"。

循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。

你的实现应该支持如下操作

  1. MyCircularQueue(k):构造器,设置队列长度为k
  2. Front:从队首获取元素。如果队列为空,返回-1
  3. Rear:获取队尾元素。如果队列为空,返回-1
  4. enQueue(value):向循环队列插入一个元素,如果成功插入则返回真
  5. deQueue():从循环队列中删除一个元素。如果成功删除则返回真
  6. isEmpty():检查循环队列是否为空
  7. isFull():检查循环队列是否已满

分析:

  • 采用数组或者链表都可以,但是数组缓存利用率更高,所以这里主要采用数组的方式。
  • 用模运算将存储空间在逻辑上变成“环状”。当发现rear指针要指向MaxSize时,不应该让它指向MaxSize而是应该让它指向数组下标为0的位置。
  • 队列判空:Q.rear==Q.front;队列判满:队尾指针的下一个位置是对头,即(Q.rear+1)%MaxSize==Q.front

代码实现: 

//循环队列的定义
typedef struct
{int* a;//动态开辟数组int k;//当前有效元素个数int head;//队头int tail;//队尾
}MyCircularQueue;//循环队列的初始化
MyCircularQueue* myCircularQueueCreate(int k)
{//为队列开辟一块动态内存空间MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));//为数组开辟一个包含(k+1)个元素的内存空间obj->a = (int*)malloc(sizeof(int) * (k + 1));//队头,队尾起始都指向数组下标为0的位置obj->head = obj->tail = 0;//当前有效元素个数设置为k个obj->k = k;return obj;
}//判断队列是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{//判空assert(obj);return obj->head == obj->tail;
}//判断队列是否已满
bool myCircularQueueIsFull(MyCircularQueue* obj)
{//判空assert(obj);int next = obj->tail + 1;//当tail指向数组最后一个下标的下一个位置时,则将tail指向数组下标为0的位置if (next == obj->k + 1){next = 0;}//队尾指针的下一个位置是对头,则表示队列已满return next == obj->head;
}//入队
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{//判空assert(obj);//检查队列是否已满if (myCircularQueueIsFull(obj)){return false;}//未满则将value插入队尾obj->a[obj->tail] = value;obj->tail++;//队尾指针后移//当tail指向数组最后一个下标的下一个位置时,则将tail指向数组下标为0的位置if (obj->tail == obj->k + 1){obj->tail = 0;}//obj->tail%=(k+1);return true;
}//出队
bool myCircularQueueDeQueue(MyCircularQueue* obj)
{//判空assert(obj);//检查队列是否为空if (MyCircularQueueIsEmpty(obj)){return false;}//若不空,则队头指针后移++obj->head;//当head指向数组最后一个下标的下一个位置时,则将head指向数组下标为0的位置if (obj->head == obj->k + 1){obj->head = 0;}return true;
}//取队头元素
int myCircularQueueFront(MyCircularQueue* obj)
{//判空assert(obj);//检查队列是否为空if (myCircularQueueIsEmpty(obj)){return -1;}//若不为空,则取队头元素return obj->a[obj->head]};//取队尾元素
int myCircularQueueRear(MyCircularQueue* obj)
{//判空assert(obj);//检查队列是否为空if (myCircularQueueIsEmpty(obj)){return -1;}//因为tail指向队尾元素的下一个位置,所以要取tail前一位置的下标int pre = obj->tail - 1;//若tail在数组起始位置,则前一位置的下标为数组的末尾位置if (obj->tail == 0){pre = obj->k;}//int pre = obj->tail - 1 + obj->k + 1;//pre %= (obj->k+1);//取队尾元素return obj->a[pre];
}//销毁
void myCircularQueueFree(MyCircularQueue* obj)
{//判空assert(obj);//释放动态开辟的数组free(obj->a);//释放队列free(obj);
}

    本期的分享已经接近尾声,内容有些多,大家耐心些哈~重点还是要关注栈和队列的四道经典例题,它们能让我们更好的掌握核心知识。或许你在看的时候感觉有些难度,不要烦躁,更不要焦虑,没有谁能一蹴而就。你需要做的便是不断地重复、重复!!最能帮助你的那双手,就长在你的胳膊上。好啦,如果这篇文章对你们有帮助,记得留下三连加支持哈~你们的支持是我创作的最大动力!诸君加油,不负自己。那我们下期再会啦!

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

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

相关文章

37、Tomato(VulnHub)

Tomato 一、nmap 2211是ssh的端口&#xff0c;21的ftp也不是弱密码 二、web渗透 随便看看 目录爆破 /seclists/Discovery/Web-Content/common.txt /antibot_image/antibots/readme.txt 发现该站点存在反爬机制 /antibot_image/antibots/info.php 提示我们该网页存在个参数 GET&…

SFP、SFP+、SFP28 与 QSFP28 收发器之间的差异:兼容性和性能

近年来&#xff0c;网络技术发展迅速&#xff0c;因此&#xff0c;计算专业人员面临着越来越令人困惑的术语和缩写词。 管理数据中心时必须了解的一个关键领域是收发器&#xff0c;特别是 SFP (1550nm/1310nm)、SFP (850nm) 和 QSFP28 (4x25G) 之间的差异。 这些型号在兼容性方…

深入浅出 SQL 优化:全面提升查询性能的技巧

文章目录 前言一、表结构分析1. 索引分析2. 数据类型分析3. 思考反范式设计的适用场景与潜在风险3.1数据冗余3.2 数据一致性3.3 更新性能 4. 关注临时表的创建与使用。4.1.尽量减少临时表的使用&#xff0c;以降低系统资源的消耗。4.2 使用合适的索引和数据类型优化临时表的性能…

HarmonyOS ArkUI实战开发-窗口模块(Window)

窗口模块用于在同一物理屏幕上&#xff0c;提供多个应用界面显示、交互的机制。 对应用开发者而言&#xff0c;窗口模块提供了界面显示和交互能力。对于终端用户而言&#xff0c;窗口模块提供了控制应用界面的方式。对于操作系统而言&#xff0c;窗口模块提供了不同应用界面的…

swiper 去掉轮播图上的小点点 小圆圈(完美解决方案)

文章目录 问题描述解决方案问题复现处理方案 问题描述 大家好&#xff01;我是夏小花&#xff0c;今天是2024年4月22日|农历三月十四&#xff0c;今天这篇博文主要解决swiper 去掉轮播图上的小点点 小圆圈&#xff0c;具体解决方案如下所示 解决方案 问题复现 现在现在可以看…

数据结构初阶-二叉树

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 二叉树 树概念和结构 树的概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限节点组成的一个具有层次关系的集合&#xff0c;把它叫做树…

python--pyQt5 进度条:QProgressBar

https://www.cnblogs.com/itwangqiang/articles/14959401.html https://blog.csdn.net/weixin_43990846/article/details/123880081 进度条用于向用户指示操作的进度&#xff0c;并向他们保证应用程序仍在运行 例 1 import sys from PyQt5.QtWidgets import QApplication, QWi…

【机器学习】特征筛选:提升模型性能的关键步骤

一、引言 在机器学习领域&#xff0c;特征筛选是一个至关重要的预处理步骤。随着数据集的日益庞大和复杂&#xff0c;特征的数量往往也随之激增。然而&#xff0c;并非所有的特征都对模型的性能提升有所贡献&#xff0c;有些特征甚至可能是冗余的、噪声较大的或者与目标变量无关…

Webpack-

定义 静态模块&#xff1a;指的是编写代码过程中的html&#xff0c;css&#xff0c;js&#xff0c;图片等固定内容的文件 打包&#xff1a;把静态模块内容压缩、整合、翻译等&#xff08;前端工程化&#xff09; 1&#xff09;把less/sass转成css代码 2&#xff09;把ES6降级…

OpenHarmony鸿蒙南向开发案例:【智能加湿器】

样例简介 智能加湿器具有实时监控其所处环境温度、湿度&#xff0c;并通过数字管家设置日程&#xff0c;自动打开加湿器控制湿度功能。显示界面使用DevEco Studio 编写的js应用&#xff0c;具有很好的兼容和移植特性。硬件上采用了带有HDF框架的驱动模型&#xff0c;通过GPIO和…

nodejs在控制台打印艺术字

const figlet require("figlet");figlet("SUCCESS", function (err, data) {if (err) {console.log("Something went wrong...");console.dir(err);return;}console.log(data);}); 参考链接&#xff1a; https://www.npmjs.com/package/figlet…

Android studio配置Flutter(看这一篇就够了)

Flutter 是 Google 推出并开源的移动应用开发框架&#xff0c;主打跨平台、高保真、高性能。开发者可以通过 Dart 语言开发 App&#xff0c;一套代码同时运行在 iOS 和 Android平台。 Flutter 提供了丰富的组件、接口&#xff0c;开发者可以很快地为 Flutter 添加 Native&#…

基于开源CrashRpt与微软开源Detours技术深度改造的异常捕获库分享

目录 1、异常捕获模块概述 2、为什么需要异常捕获模块&#xff1f; 3、在有些异常的场景下是没有生成dump文件的 4、开源异常捕获库CrashRpt介绍 5、对开源库CrashRpt的改进 C软件异常排查从入门到精通系列教程&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持…

【图说】VMware Ubuntu22.04 详细安装教程

前言 无论是从事 Linux 开发工作&#xff0c;还是希望电脑运行双系统&#xff0c;VMware 虚拟机都是我们日常工作不可或缺的工具。本章将会重点介绍 VMware 安装流程&#xff0c;以及在 VMware 上如何运行、使用 Ubuntu22.04 系统。 一、VMware 下载安装 1.1 VMware 官网下载…

TensorFlow文件读取 --TFRecords文件

TFRecords文件 是一种二进制文件&#xff0c;能够很好的利用内存&#xff0c;更方便复制和移动&#xff0c;并且不需要单独的标签文件 使用步骤 1&#xff09;获取数据 2&#xff09;将数据填入到Example协议内存块&#xff08;protocol buffer&#xff09; 3&#xff09;将协…

001-谷粒商城-微服务剖析

1、架构图 还是很强的&#xff0c;该有的都有 2、微服务模块 SpringCloudAlibaba组件包括 SentinelNacosRocketMQSeata 搭配SpringCloudAlibaba组件 OpenFeignGateWayRibbn gateway使用了SpringWebFlux&#xff0c;前几天研究到&#xff0c;为什么springboot不直接使用Spri…

阿里云mysql8.0 this is incompatible withsql mode=only full group by

阿里云RDS中mysql5.6升级为8.0后&#xff0c;出现如下问题&#xff1a; ### Error querying database. Cause:java.sql.SQLSyntaxErrorException: Expression #1 of SELECT listis not in GROUP BY clause and contains nonaggregatedcolumn temp.product_id which is not fun…

2024抖店新政策!抖音小店的发展趋势!新手必看!

哈喽~我是电商月月 准备开抖店的新手朋友注意了&#xff0c;最近抖音严查无货源违规商家&#xff0c;还发布了取消新手期的政策&#xff0c;这说明了两点 1. 生态环境正在改变 无规矩不成方圆&#xff0c;违规的都是故意放错类目以及&#xff0c;靠S单非法获得销量&#xff…

流量计如何进行校准?

什么是流量计&#xff1f;流量计是指示被测流量和&#xff08;或&#xff09;在选定的时间间隔内流体总量的仪表。简直研制&#xff0c;流量计是用于测量管道或明渠中流体流量的一种仪表。流量计种类繁多&#xff0c;又分为有差压式流量计、转子流量计、节流式流量计、细缝流量…

Linux信号(保存)

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 前言 Linux信号(产生)-CSDN博客&#xff0c;上一个章节我们详细介绍了信号是什么&#xff0c;为什么要有信号&#xff0c;怎样产生信号&#xff0c;以及信号产生的几个问题&#xff0c;这个章节我们将介绍信号的保存。 我们…