队列的实现(附含三道经典例题)

news2024/11/19 8:48:49

🍉文章主页:阿博历练记
📖文章专栏:数据结构与算法
🚍代码仓库:阿博编程日记
🍥欢迎关注:欢迎友友们点赞收藏+关注哦🌹

在这里插入图片描述

文章目录

    • 🌾前言
    • 🎬队列
      • 🔍1.队列的结构框架
      • 🔍2.队列的初始化
      • 👑为什么初始化不使用二级指针
      • 🔍3.队列的释放
      • 🔍4.队列的插入数据
      • 🔍5.队列的删除数据
      • 🔍6.队列取队头数据
      • 🔍7.队列取队尾数据
      • 🔍8.返回队列数据的个数
      • 🔍9.判断队列是否为空
      • 🚀Queue.h代码
      • 🛸Queue.c代码
      • 🛳Test.c代码
      • 🧋代码效果展示
      • 1.🖋题目描述
      • 💡逻辑分析
      • 🎥代码实现
      • 2.🖋题目描述
      • 💡逻辑分析
      • 🎥代码实现
      • 3.🖋题目描述
      • 📝循环队列
      • 💡逻辑分析
      • ⭐解决方案
      • 🔔误区1(插入删除数据的取模处理)
      • 🔔误区2(访问队尾数据)
      • 🎥代码实现

🌾前言

友友们,上期阿博给大家介绍了栈的实现,今天阿博给大家介绍一种新的数据结构:队列.
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)的性质。
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
在这里插入图片描述
队列也可以使用数组链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低.
在这里插入图片描述
在这里插入图片描述

🎬队列

🔍1.队列的结构框架

typedef  int QDataType;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType  data;
}QNode;
typedef struct  Queue
{
	QNode* phead;
	QNode* ptail;
	int  size;
}Queue;

⛳⛳友友们注意,这两个结构体不能合并到一起,因为它们所代表的意义不一样,第一个结构体是每一个结点的结构,第二个结构体代表的是这个队列的结构,它表示的是队列整体.

🔍2.队列的初始化

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

👑为什么初始化不使用二级指针

⛳⛳这里有可能友友们会有疑问,我们初始化不是要改变phead指针和ptail指针,它们两个都是结构体指针,我们要改变它们,为什么不用二级指针呢?这里友友们注意了,phead指针和ptail指针又在一个新的结构体Queue里面放着,它们就属于这个结构体里面的成员,我们要改变它,只需要传这个新结构体的地址就可以访问并改变它们了.
这里阿博给友友们总结几种不用二级指针的方法:
⭐1.我们在函数外部定义一个同类型的指针,通过返回值的方式接收,这本质上是一个值拷贝(赋值)
⭐2.带哨兵位的头结点,它的本质是改变结构体里面的next指针,next指针属于结构体的成员,所以我们只需要传结构体的指针就可以访问到它了.
⭐3.把结构体指针重新放在一个结构体里面,这样它就属于这个结构体的成员了,我们只需要传这个结构体的地址就可以改变结构体指针了.

🔍3.队列的释放

1.保存下一结点的地址迭代释放

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;
}

2.保存当前结点的地址迭代释放

void  QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->phead;
	while (cur)
	{
	    QNode* del = cur;
		cur = cur->next;
		free(del);
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

🚩🚩友友们,这里要注意两个点:⭐1.如果保存当前结点的地址的话,我们就需要先让cur=cur->next往后迭代,然后在释放保留的那个地址,如果先释放的话,那么cur=cur->next这一步就会报错,此时cur已经被释放了,我们还在使用,它就是一个野指针.⭐2.如果保留下一结点地址的话,我们就需要先释放当前结点,在让cur=next往后进行迭代,如果我们先往后迭代的话,此时cur=next已经指向下一结点了,我们在把它释放,这样就会导致上一个结点没有释放和下次再使用cur就是野指针.🌈🌈

🔍4.队列的插入数据

void  QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;
	if (pq->phead == NULL)
	{
		assert(pq->ptail == NULL);
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}

⛳⛳友友们注意,就算这里是首次插入数据,我们也不需要二级指针因为phead和ptail指针都在结构体里面放着,所以我们传这个结构体的指针就可以改变它们.

🔍5.队列的删除数据

错误案例

void  QueuePop(Queue* pq)
{
        assert(pq);
        QNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
		pq->size--;
}	

在这里插入图片描述
代码纠正

void  QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	//1个结点
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead =pq->ptail= NULL;     //不能对同一动态开辟出来的空间进行多次free释放,这里我们释放完pq->phead之后,pq->ptail也已经被释放了,所以我们主要的目的就是把pq->phead和pq->ptail都置空
	}
	//多个结点
	else
	{
		QNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}
	pq->size--;
}

⛳⛳友友们注意,pq->phead和pq->ptail指向相同的结点,free(pq->phead)之后就已经把这块内存空间释放了,此时我们就不能再free(pq->ptail)了,因为动态开辟出来的空间不能进行多次free释放.

🔍6.队列取队头数据

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

这里我们需要断言队列不能为空,如果为空,pq->phead就是空指针,这时pq->phead->data就是对空指针的解引用,程序就会报错.

🔍7.队列取队尾数据

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

🔍8.返回队列数据的个数

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

🔍9.判断队列是否为空

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

🚀Queue.h代码

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

typedef  int QDataType;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType  data;
}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);
int   QueueSize(Queue* pq);
bool  QueueEmpty(Queue* pq);

🛸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  QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
		/*QNode* del = cur;
		cur = cur->next;
		free(del);*/
	}
	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->data = x;
	newnode->next = NULL;
	if (pq->phead == NULL)
	{
		assert(pq->ptail == NULL);
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}
void  QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	//1个结点
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail=NULL;     //不能对同一动态开辟出来的空间进行多次free释放,这里我们释放完pq->phead之后,pq->ptail也已经被释放了,所以我们主要的目的就是把pq->phead和pq->ptail都置空
	}
	//多个结点
	else
	{
		QNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}
	pq->size--;
}
QDataType  QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return  pq->phead->data;
}
QDataType  QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return  pq->ptail->data;
}
int   QueueSize(Queue* pq)
{
	assert(pq);
	return  pq->size;
}
bool  QueueEmpty(Queue* pq)
{
	assert(pq);
	return  pq->phead == NULL
		&&  pq->ptail == NULL;
}

🛳Test.c代码

#define  _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"
#include<stdio.h>
TestQueue()
{
	Queue  q;
	QueueInit(&q);

	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);
	while (!QueueEmpty(&q))
	{
		printf("%d ", QueueFront(&q));
		QueuePop(&q);
	}
	QueueDestroy(&q);
	return  0;
}
int main()
{
	TestQueue();
	return  0;
}

🧋代码效果展示

在这里插入图片描述

1.🖋题目描述

在这里插入图片描述

💡逻辑分析

在这里插入图片描述

友友们,通过这里也可以看出我们的入栈顺序是1,2,3,我们的出栈顺序也是1,2,3.

🎥代码实现

typedef  int  STDataType;
typedef struct  Stack
{
	STDataType* a;
	int top;                    //top指向栈顶的位置
	int capacity;
}ST;

void  STInit(ST* pst);
void  STDestroy(ST* pst);
void  STPush(ST* pst,STDataType x);
STDataType  STTop(ST* pst);
void  STPop(ST* pst);
bool  STEmpty(ST* pst);
int   STSize(ST* pst);

void  STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->top = 0;    //如果我们初始化为0,top就指向栈顶元素的下一个位置,初始化为-1,top就是指向栈顶元素.
	pst->capacity = 0;
}
void  STDestroy(ST* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->capacity = pst->top = 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,newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	} 
	pst->a[pst->top] = x;
	pst->top++;
}
STDataType  STTop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	return pst->a[pst->top - 1];
}
bool  STEmpty(ST* pst)
{
	assert(pst);
	return  pst->top == 0;
}
void  STPop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	pst->top--;
}
int   STSize(ST* pst)
{
	assert(pst);
	return   pst->top;
}

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


MyQueue* myQueueCreate() {
   MyQueue*obj=(MyQueue*)malloc(sizeof(MyQueue));
   if(obj==NULL)
   {
       perror("malloc fail");
       return;
   }
   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))
  {
      while(!STEmpty(&obj->pushst))
      {
      STPush(&obj->popst,STTop(&obj->pushst));
      STPop(&obj->pushst);
      }
  }
  return  STTop(&obj->popst);
}

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

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

2.🖋题目描述

在这里插入图片描述

💡逻辑分析

在这里插入图片描述

🎥代码实现

typedef  int QDataType;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType  data;
}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);
int   QueueSize(Queue* pq);
bool  QueueEmpty(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;
		/*QNode* del = cur;
		cur = cur->next;
		free(del);*/
	}
	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->data = x;
	newnode->next = NULL;
	if (pq->phead == NULL)
	{
		assert(pq->ptail == NULL);
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}
void  QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	//1个结点
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead =pq->ptail= NULL;     //不能对同一动态开辟出来的空间进行多次free释放,这里我们释放完pq->phead之后,pq->ptail也已经被释放了,所以我们主要的目的就是把pq->phead和pq->ptail都置空
	}
	//多个结点
	else
	{
		QNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}
	pq->size--;
}
QDataType  QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return  pq->phead->data;
}
QDataType  QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return  pq->ptail->data;
}
int   QueueSize(Queue* pq)
{
	assert(pq);
	return  pq->size;
}
bool  QueueEmpty(Queue* pq)
{
	assert(pq);
	return  pq->phead == NULL
		&&  pq->ptail == NULL;
}


typedef struct {
   Queue  p;
   Queue  q;
} MyStack;


MyStack* myStackCreate() {
  MyStack*obj=(MyStack*)malloc(sizeof(MyStack));
  if(obj==NULL)
  {
      perror("malloc fail");
      return;
  }
  QueueInit(&obj->p);
  QueueInit(&obj->q);
   return  obj;
}

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

int myStackPop(MyStack* obj) {
      Queue* NoFull=&obj->p;
      Queue*  Full=&obj->q;
      if(QueueEmpty(&obj->p))
      {
          Full=&obj->p;
          NoFull=&obj->q;
      }
      while(QueueSize(NoFull)>1)
      {
          QueuePush(Full,QueueFront(NoFull));
          QueuePop(NoFull);
      }
      int top=QueueBack(NoFull);
      QueuePop(NoFull);
      return  top;
}

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

bool myStackEmpty(MyStack* obj) {
return   QueueEmpty(&obj->p)
         &&QueueEmpty(&obj->q);
}

void myStackFree(MyStack* obj) {
   QueueDestroy(&obj->p);
   QueueDestroy(&obj->q);
   free(obj);
}

3.🖋题目描述

在这里插入图片描述

📝循环队列

友友们,我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型时可以就会使用循环队列。环形队列可以使用数组实现,也可以使用循环链表实现。
在这里插入图片描述
在这里插入图片描述

💡逻辑分析

在这里插入图片描述

⭐解决方案

在这里插入图片描述

⛳⛳友友们注意,这里我们删除数据的时候不需要抹除数据,我们只需要把front指针往后移动就行,因为我们是认为front和rear之间的数据为有效的数据,而且rear的位置是可以存放数据的,因为它是队尾数据的下一个位置,所以即使它有数据,无论如何我们也访问不到.

在这里插入图片描述

🔔误区1(插入删除数据的取模处理)

友友们注意,这里我们入数据之后,也不能只让rear++.
在这里插入图片描述
同理,当我们删除数据的时候,也不能只让front++,我们在加加之后也要进行取模处理.

🔔误区2(访问队尾数据)

在这里插入图片描述

🎥代码实现

typedef struct {
    int  front;
    int  rear;
    int  k;
    int*a;
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {
     MyCircularQueue*obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
     obj->a=(int*)malloc(sizeof(int)*(k+1));
     obj->front=obj->rear=0;
     obj->k=k;
     return   obj;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
     return  (obj->rear+1)%(obj->k+1)==obj->front;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
      return  obj->front==obj->rear;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
       if(myCircularQueueIsFull(obj))
       return   false;
       obj->a[obj->rear]=value;
       obj->rear++;
       obj->rear%=(obj->k+1);
       return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
       if(myCircularQueueIsEmpty(obj))
       return  false;
       obj->front++;
       obj->front%=(obj->k+1);
       return  true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
       if(myCircularQueueIsEmpty(obj))
         return   -1;
       return   obj->a[obj->front]; 
}

int myCircularQueueRear(MyCircularQueue* obj) {
     if(myCircularQueueIsEmpty(obj))
        return   -1;
      return  obj->a[(obj->rear+obj->k)%(obj->k+1)];  
}


void myCircularQueueFree(MyCircularQueue* obj) {
     free(obj->a);
     obj->a=NULL;
     free(obj);
}

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

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

相关文章

HACK ME PLEASE: 1

文章目录 HACK ME PLEASE: 1实战演练一、前期准备1、相关信息 二、信息收集1、访问网站2、端口扫描2、扫描目录3、访问网站4、访问网站5、扫描目录6、访问网站7、登录MySQL数据库8、查看数据表9、查看users表的内容10、查看tblUsers表内容11、解密12、加密13、修改密码14、查询…

解决Ubuntu 22.04 程序以管理员权限运行无法播放声音

文章目录 摘要需求背景问百度问GPT最终解决方案,这篇文章的核心第一步,把root账户加入到组里面,第二步,编写一个服务文件第三步,允许这个文件第四步,启动服务第五步,修改Config文件第六步,重启电脑关键字: Qt、 pulseaudio、 管理员、 声音、 服务 摘要 这个是我…

CentOS 7.9配置SSH免密登录(无需合并authorized_keys)

场景&#xff1a;在CentOS 7.9操作系统上&#xff0c;配置SSH免密登录&#xff0c;以满足集群中应用的控制脚本能够依赖SSH来执行针对整个集群的操作。 版本&#xff1a; 操作系统&#xff1a;CentOS 7.9 1.配置SSH免密登录原因 (1)规划安装和部署的组件在运行时&#xff0…

科技云报道:ChatGPT的胜利,宣告知识图谱的消亡?

科技云报道原创。 过去10年&#xff0c;知识图谱可谓是最接近“人工智能”的概念。业内普遍认为&#xff0c;知识图谱的概念最先是由谷歌于2012年正式提出&#xff0c;主要用来支撑下一代搜索和在线广告业务。 此后&#xff0c;这项技术迅速火爆&#xff0c;被国内外多家搜索…

FasterTransformer5.0编译安装与测试

基础环境&#xff1a;centos7 cuda10.2cudnn7 显卡&#xff1a;Tesla V100 1 C编译准备 代码准备&#xff1a; git clone -b release/v5.0_tag https://github.com/NVIDIA/FasterTransformer.git mkdir -p FasterTransformer/build cd FasterTransformer/build git submodu…

2023年还有人在纠结如何学习黑客知识?

首先我谈下对黑客&网络安全的认知&#xff0c;其实最重要的是兴趣热爱&#xff0c;不同于网络安全工程师&#xff0c;他们大都是培训机构培训出来的&#xff0c;具备的基本都是防御和白帽子技能&#xff0c;他们绝大多数的人看的是工资&#xff0c;他们是为了就业而学习&am…

【国产虚拟仪器】基于AD9172/AD9176的4 通道12.6GSPS 采样率16 位DA 播放FMC JESD204B 接口子卡模块

板卡概述 FMC_XM131 是一款4 通道12.6GSPS 采样率16 位DA 播放FMC子卡模块&#xff0c;该板卡为FMC标准&#xff0c;符合VITA57.4 规范&#xff0c;可以作为一个理想的IO 模块耦合至FPGA 前端&#xff0c;16 通道的JESD204B 接口通过FMC连接器连接至FPGA 的高速串行端…

day7 - 使用几何变换让图像动起来

本期将了解图像的几何变换。几何变换是指改变图像的几何结构&#xff0c;例如大小、角度和形状等&#xff0c;让图像呈现出缩放、翻转、映射和透视的效果。 完成本期内容&#xff0c;你可以&#xff1a; 了解几何变换的定义掌握几何变换的原理和使用 若要运行案例代码&#…

【正点原子STM32连载】 第十五章 按键输入实验 摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第十五…

Vue之MVVM模型

文章目录 前言一、简说MVVM模型二、走进MVVM总结 前言 Vue的创建者在创建Vue时没有完全遵守MVVM&#xff08;一种软件架构模式&#xff09;&#xff0c;但是Vue的设计受到了他它的启发。这也是为什么经常用vm&#xff08;ViewModel的缩写&#xff09;这个变量名表示Vue实例。 …

服了呀,被现在的00后卷麻了....

现在的小年轻真的卷得过分了。前段时间我们公司来了个00年的&#xff0c;工作没两年&#xff0c;跳槽到我们公司起薪18K&#xff0c;都快接近我了。后来才知道人家是个卷王&#xff0c;从早干到晚就差搬张床到工位睡觉了。 最近和他聊了一次天&#xff0c;原来这位小老弟家里条…

docker创建emqx容器,emqx版本4.4.9

题记&#xff1a;网上找了很多文章&#xff0c;都没能怎么说明白如何对mqtt连接通信做认证&#xff0c;也就是tcp方式的时候&#xff0c;携带user、password&#xff0c;很苦恼&#xff0c;最后找了一大圈&#xff0c;说emqx的4.4.9版本的Dashboard有插件&#xff0c;果然顺藤摸…

vue动态class的写法

本文会详细介绍 vue动态 class的写法&#xff0c;并且提供一些我个人的理解&#xff0c;希望对你有所帮助。 如果你是一个新手&#xff0c;或者想了解 vue的源码&#xff0c;那么首先应该学习 vue的基础知识&#xff0c;比如&#xff1a;什么是静态语言&#xff0c;有什么作用等…

155. 最小栈

题目描述&#xff1a; 主要思路&#xff1a; 利用辅助栈来实现&#xff0c;一个最小栈用类似于单调栈的方法进行维护&#xff0c;具体见代码。 class MinStack { private:stack<int> x;stack<int> minx; public:MinStack() {minx.push(INT_MAX);}void push(int v…

IMX6ULL的I2C驱动详细分析

IMX6ULL的I2C驱动详细分析 文章目录 IMX6ULL的I2C驱动详细分析i2c_imx_driver 的平台驱动注册i2c_imx_probe注册函数i2c_imx_algoI2C算法结构体i2c_imx_start开始I2Ci2c_imx_stop停止I2Ci2c_imx_isr中断服务函数i2c_imx_dma_writeDMA 进行写操作的 I2C 传输2c_imx_dma_readi2c_…

动图怎么拆分成静图?简单快速分解gif的方法

怎么把gif动图变成静态图片&#xff1f;常见的gif动图画面生动丰富&#xff0c;是由一帧一帧静态的图片合成的&#xff0c;当我们想要把gif动图拆分成多张图片的时候要怎么操作呢&#xff1f;有没有什么简单方便的工具吗&#xff1f; 一、有没有简单方便的gif工具呢&#xff1…

Linux内存简介

Linux内存简介 概述 为何MemTotal小于RAM容量 [rootiZbp1dphe2bpv39op1g123Z ~]# dmesg | grep Memory [ 1.391064] Memory: 131604168K/134217136K available (14346K kernel code, 9546K rwdata, 9084K rodata, 2660K init, 7556K bss, 2612708K reserved, 0K cma-reserved) …

云原生改造- istio

istio 官网有bookinfo的案例&#xff0c; 但是这个案例过于繁琐&#xff0c;直接就可以运行&#xff0c;但是有些原理不是很清楚。 本教程是k8s改造成istio一个案例。spring-petclinic-msa是网上找到的一个k8s的一个java案例&#xff0c;通过spring-petclinic-msa改造成istio&a…

盘点团队在线帮助文档怎么做?

团队在线帮助文档是一个非常重要的工具&#xff0c;它可以帮助团队成员更好地协作和沟通&#xff0c;提高工作效率&#xff0c;并减少沟通成本。在本文中&#xff0c;我们将会盘点团队在线帮助文档的各个方面&#xff0c;以帮助您更好地了解如何创建一个高效的在线帮助文档。 …

6. python的for循环

文章目录 一、for循环1.1、for循环分析1.2、注意事项 二、遍历数值列表2.1、range()函数的使用2.2、 创建数值列表2.3、对数值列表进行简单统计 一、for循环 有时&#xff0c;我们需要对列表内的所有元素逐一进行相同的操作&#xff0c;为避免出现大量重复的代码&#xff0c;p…