当前位置: 首页 > ai >正文

顺序队列和链式队列

顺序队列和链式队列

根据上一篇博客我们可以明显的知道,基础结构加约束会对我们处理某些数据更加的方便,而上篇讲的是在一端维护,而我们这一次讲的是在两端维护也就是我们今天要讲的数据结构——队列

顺序队列

插入和删除分别在两端进行,就像我们进行排队一样,从队尾插入,从队头删除,如何插入这必须需要指针指向队头和队尾。

关于指针,我们要说明的,我们所说的指针不一定是语言中的指针,它是一种我们需要待插入的位置,可以是指针,也可以是下标。

一开始我们可以认为队整个都是空的

队头==队尾

//rear 队头
//front 队尾
rear==front;

在这里插入图片描述

现在我们将一个数插入进去

假设这一数组叫 int*data

我们入队操作就可以这样写

data[rear]=v1;
++rear;

然后根据队尾指针我们就可以知道如何出队操作

x1=data[front];
++front;

不知道你发现没有,这里入队和出队的操作,其实感觉动作差不多,结合我们上一篇栈的知识,我们可以明显的发现

栈的入栈和出栈的动作是相反的,而队列入队和出队的动作是相同的,那么我们在颠倒一下位置这不就是另一种写法了吗?

//入队
++rear;
data[rear]=v1;
//出队
++front;
x1=data[front];

如图

在这里插入图片描述

很好,这个明白了之后,我们在想想

当我们一共定义了八个空间,全都填满了,然后出队四个空间,请问我们这个空间满了吗?

看似满了,但是这种情况我们称之为顺序对列的假溢出

其实没有满

在这里插入图片描述

你之前已经出队的空间其实完全可以废品回收再利用。

这种处理数据的方法我们可以叫循环队列

顺序队列和循环队列如图

在这里插入图片描述

队尾队头操作行为

rear=(rear+1)%maxSize;
front=(front+1)%maxSize;

我们可以使用求模的方法达到循环的目的

那我们队列是空还是满如何判断呢?

如果按照以前的方法

全都是

rear==front

那我们又应该如何区分呢?

我们可以用浪费空间法,浪费一个空间来进行对满的判断。

if((rear+1)%N!=front)
{data[rear]=v1;rear=(rear+1)%N;
}

在这里插入图片描述

当到后面时会先试探一下,如果满了就直接跳过。

既然已经解决了队列判满的问题,我们就可以按照原来的方法对队列进行判空操作

front=rear;

我们来定义一个队列的结构体

struct arrayQueue{element data[max];int front;int rear;
};

按照这个我们来实现

顺序队列实现

结构定义和结构操作的声明

#define QUEUE_SIZE 5typedef struct {Element data[QUEUE_SIZE];int front;int rear;
}ArrayQueue ;void initArrayQueue(ArrayQueue *Q);int enQueue(ArrayQueue *Q,Element e);int deQueue(ArrayQueue *Q,Element *e);

结构操作的实现

void initArrayQueue(ArrayQueue *Q) {Q->front=Q->rear=0;
}int enQueue(ArrayQueue *Q, Element e) {if ((Q->rear+1)%QUEUE_SIZE==Q->front) {fprintf(stderr,"Queue is full\n");return -1;}Q->rear=(Q->rear+1)%QUEUE_SIZE;Q->data[Q->rear]=e;return 0;
}int deQueue(ArrayQueue *Q, Element *e) {if (Q->rear==Q->front) {fprintf(stderr,"Queue is empty\n");return -1;}Q->front=(Q->front+1)%QUEUE_SIZE;*e=Q->data[Q->front];return 0;
}

测试

void text1() {ArrayQueue ate;initArrayQueue(&ate);for(int i = 0; i < 4; i++) {enQueue(&ate,i+100);}enQueue(&ate,1);printf("Dequeue ");Element m;while (deQueue(&ate,&m)!=-1) {printf("%d\t ", m);}printf("\n");
}

结果

在这里插入图片描述

说完顺序队列我们再来说一说链式队列

链式队列

对于有些情况我们是不知道数据有多少的,这时候就需要我们用链式队列去解决问题。

当我们插入一个元素我们应该在一个元素的后面去插入。

在这里插入图片描述

那有人就要问了,为啥不能像栈一样从前面开始插入?

你可以仔细看看,从前面插入的话我们出队又该如何操作呢?

自然是操作不了,所以我们还是向后操作

其实说实在的就是尾插法

rear->next=new_node;
rear=new_node;

那么删除自然也就知道了

tmp=front;
front=temp->next;
free(tmp)

链式队列的实现

结构定义和结构操作的声明

typedef struct _node {Element data;struct _node *next;}QueNode;
//队头
typedef struct {QueNode *front;QueNode *rear;int cnt;const char*name;
}LinkQueue;//初始化
LinkQueue* createLinkQueue(const char* name);
void deleteLinkQueue(LinkQueue* queue);int EnQueue(LinkQueue* queue, Element e);
int EeQueue(LinkQueue* queue, Element* e);

结构操作实现


#include "LinkQueue.h"#include <stdio.h>
#include <stdlib.h>LinkQueue * createLinkQueue(const char*name) {LinkQueue* queue = (LinkQueue*)malloc(sizeof(LinkQueue));if (queue == NULL) {printf("Memory allocation failed\n");return NULL;}queue->cnt=0;queue->name=name;queue->front=queue->rear=NULL;return queue;}void deleteLinkQueue(LinkQueue *queue) {if (queue) {QueNode*node;while (queue->front) {node = queue->front;queue->front=node->next;free(node);queue->cnt--;}printf("queue deleted %d\n",queue->cnt);free(queue);}
}//入队
int EnQueue(LinkQueue *queue, Element e) {QueNode*node = (QueNode*)malloc(sizeof(QueNode));if (node == NULL) {printf("Memory newnode failed\n");return -1;}node->data = e;node->next = NULL;if (queue->rear) {queue->rear->next = node;queue->rear = node;}else {queue->front=queue->rear = node;}queue->cnt++;return 0;
}int EeQueue(LinkQueue *queue, Element *e) {if (queue->rear == NULL) {printf("Queue is empty\n");return -1;}*e=queue->front->data;QueNode*tmp=queue->front;queue->front=tmp->next;free(tmp);queue->cnt--;if (queue->front == NULL) {queue->rear = NULL;}return 0;
}

测试

void text2() {LinkQueue*queue=createLinkQueue("ste1");if (queue==NULL) {return;}for(int i = 0; i < 4; i++) {EnQueue(queue,i+100);}Element s1;printf("%s que %dshow\n",queue->name,queue->cnt);while(EeQueue(queue,&s1)!=-1) {printf("\t%d",s1);}printf("\n");deleteLinkQueue(queue);
f("\t%d",s1);}printf("\n");deleteLinkQueue(queue);
}

结果

在这里插入图片描述

这篇博客到这里就结束了,你学会了吗?喜欢就点点赞吧(๑′ᴗ‵๑)I Lᵒᵛᵉᵧₒᵤ❤

http://www.xdnf.cn/news/15189.html

相关文章:

  • HTML(上)
  • 混合精度训练:梯度缩放动态调整的艺术与科学
  • day4--上传图片、视频
  • AI软件出海SEO教程
  • 从 Spring 源码到项目实战:设计模式落地经验与最佳实践
  • nginx反向代理实现跨域请求
  • 基于springboot+Vue的二手物品交易的设计与实现
  • ABP VNext + OpenTelemetry + Jaeger:分布式追踪与调用链可视化
  • C语言32个关键字
  • WebGL简易教程——结语
  • 可穿戴智能硬件在国家安全领域的应用
  • Openpyxl:Python操作Excel的利器
  • 10. 垃圾回收的算法
  • JVM 中“对象存活判定方法”全面解析
  • java单例设计模式
  • 小白入门:通过手搓神经网络理解深度学习
  • 6. JVM直接内存
  • 机器学习(ML)、深度学习(DL)、强化学习(RL)关系和区别
  • Linux之如何用contOs 7 发送邮件
  • LeetCode 3169.无需开会的工作日:排序+一次遍历——不需要正难则反,因为正着根本不难
  • 【Modern C++ Part9】Prefer-alias-declarations-to-typedefs
  • 【PTA数据结构 | C语言版】出栈序列的合法性
  • 使用FastAdmin框架开发二
  • Python 实战:构建 Git 自动化助手
  • 昇腾FAQ-A06-行业应用MindX相关
  • hiredis: 一个轻量级、高性能的 C 语言 Redis 客户端库
  • 【世纪龙科技】新能源汽车结构原理体感教学软件-比亚迪E5
  • 代码训练LeetCode(45)旋转图像
  • 知识蒸馏中的教师模型置信度校准:提升知识传递质量的关键路径
  • git版本发布