数据结构顺序队列及链式队列

1319 字
7 分钟
数据结构顺序队列及链式队列

————————————本栏目旨在讨论计算机知识,欢迎交流————————————— 上一章,我们讨论了顺序栈和链式栈,这一章,我们将讲解线性结构的最后一个部分——顺序队列和链式队列。相比于栈结构的同端进出,就像原肠生物,而队列则是尾部入队和头部出队,就像后口生物一样。 如图: 那么,如何来实现入队和出队呢?答曰:请看VCR: 但是,使用这种直观地朴素方法我们有个致命的问题——假溢出问题。在顺序栈的实现中我们的队头队尾类似于双指针滑动窗口算法,但是每次划过了之后空间不会清除,导致看起来一共占了(rear-head)个空间,但是其实远远不止这么多。前面的都没删除,很容易产生假溢出的效果并且及其占用空间。 于是,循环赋值的方法应运而生。它的基本原理是:通过取余操作来覆盖删除的数值,直到队头与队尾相撞结束。那么,现在我们有两种思路:1、通过设定一个bool类型变量flag,每次通过判断来操作。2、虚空一个空间,每次入队的时候探针向前虚指,碰到了头才操作。比起第一种方法,第二种用了空间换时间的方法,效率更高。 如下:

if ((queue->rear + 1) % MaxQueueSize == queue->front) {
fprintf(stderr, "Queue Full!\n");
return -1;
}
//如果相等,则表明队列是满的
queue->rear = (queue->rear + 1) % MaxQueueSize;
queue->data[queue->rear] = e;
//入队操作
if (queue->rear == queue->front) {
fprintf(stderr, "Queue Empty!\n");
return -1;
}
//如果对撞,表明队列是空了
queue->front = (queue->front + 1) % MaxQueueSize;
*e = queue->data[queue->front];
//出队操作

好了,解决了顺序结构的难点,我们可以附上全部代码了: 1、.h文件的代码:

#ifndef ARRAY_QUEUE_H
#define ARRAY_QUEUE_H
#define MaxQueueSize 5
#define Element int
typedef struct {
Element data[MaxQueueSize];
int front;
int rear;
} ArrayQueue;
void initArrayQueue(ArrayQueue *queue);
int enArrayQueue(ArrayQueue *queue, Element e);
int deArrayQueue(ArrayQueue *queue, Element *e);
#endif //ARRAY_QUEUE_H

2、.c文件的代码:

#include
#include "arrayQueue.h"
void initArrayQueue(ArrayQueue* queue) {
queue->front = queue->rear = 0;
}//初始化
int enArrayQueue(ArrayQueue* queue, Element e) {
if ((queue->rear + 1) % MaxQueueSize == queue->front) {
fprintf(stderr, "Queue Full!\n");
return -1;
}
queue->rear = (queue->rear + 1) % MaxQueueSize;
queue->data[queue->rear] = e;
return 0;
}//入队
int deArrayQueue(ArrayQueue* queue, Element* e) {
if (queue->rear == queue->front) {
fprintf(stderr, "Queue Empty!\n");
return -1;
}
queue->front = (queue->front + 1) % MaxQueueSize;
*e = queue->data[queue->front];
return 0;
}//出队

既然我们已经明晰了顺序队列的循环优化方法,那么我们下一步可以继续介绍链式队列的实现方式了: 链式队列仍是遵循之前我们讲的逻辑结构的原理,但是对于链式队列,我们要重新构建队列结构,考虑到入队是插入的模式,相对自由,于是我们着重构建出队:以单链表的模式,出队的构建即为顺着单链表Next的指向方向来移动权当出队的操作。那么入队则为单向链式结构不停地增加新节点,形成同向出入队的效果。 有了一个关于模型的思考雏形,那么我们可以试着作出逻辑图如下: 下面,我们来通过代码实现它: 1、首先是.h文件功能实现的构建:

#ifndef LINK_QUEUE_H
#define LINK_QUEUE_H
#define Element int
// 链表的节点
typedef struct _node {
Element data;
struct _node *next;
} QueNode;
// 链式队列的头节点,记录队头和队尾的位置
//const char name 是队列的名字,cnt 记录元素个数
typedef struct {
QueNode *rear;
QueNode *front;
int cnt;
const char *name;
} LinkQueue;
LinkQueue *createLinkQueue(const char *name);
void releaseLinkQueue(LinkQueue *queue);
int enLinkQueue(LinkQueue *queue, Element e);
int deLinkQueue(LinkQueue *queue, Element *e);
#endif //LINK_QUEUE_H

2、建立队列的函数:

LinkQueue* createLinkQueue(const char *name) {
LinkQueue* queue = malloc(sizeof(LinkQueue));
if (queue == NULL) {
fprintf(stderr, "createLinkQueue malloc failed!\n");
return NULL;
}
queue->name = name;
queue->front =queue->rear = NULL;
queue->cnt = 0;
return queue;
}

3、 销毁队列函数:

void releaseLinkQueue(LinkQueue* queue) {
//如果队列存在
if (queue) {
//新建辅助节点
QueNode *node;
while (queue->front) {
node = queue->front;
queue->front = node->next;
//释放辅助节点
free(node);
queue->cnt--;
}
printf("queue have %d node!\n", queue->cnt);
//释放链式头结点
free(queue);
}
}

4、出队与入队:

// 先有新节点,新节点应该rear的next方向插入,便于front的删除
int enLinkQueue(LinkQueue* queue, Element e) {
QueNode *node = malloc(sizeof(QueNode));
if (node == NULL) {
fprintf(stderr, "enLinkQueue new_node malloc failed!\n");
return -1;
}//如果空间申请未成功
node->data = e;//赋值
node->next = NULL;//入队后队尾指向NULL;
if (queue->rear) {//队尾存在
queue->rear->next = node;//入队操作,和上一个过程的队尾链接
queue->rear = node;
} else {
queue->rear = queue->front = node;//初始的时候队尾队头指向同一点
}
queue->cnt++;
return 0;
}
int deLinkQueue(LinkQueue* queue, Element* e) {
if (queue->front == NULL) {
fprintf(stderr, "queue 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;
}

测试函数:

#include
#include "arrayQueue.h"
#include "linkQueue.h"
void test01() {
ArrayQueue stu1;
initArrayQueue(&stu1);
for (int i = 0; i name, queue->cnt);
while (deLinkQueue(queue, &x1) != -1) {
printf("\t%d", x1);
}
printf("\n");
releaseLinkQueue(queue);
}
int main() {
test02();
return 0;
}

好了,关于队列的数据结构结构实现讲解到此完结~撒花✿✿ヽ(°▽°)ノ✿,希望能对你有所帮助!

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!

打赏
数据结构顺序队列及链式队列
https://firefly.cuteleaf.cn/posts/knowledge/数据结构顺序队列及链式队列/
作者
Firefly
发布于
2026-06-21
许可协议
CC BY-NC-SA 4.0
相关文章 智能推荐
1
数据结构之顺序栈与链式栈
数据结构 ——————————————本文旨在交流计算机技术,欢迎指正————————————— 上一大章,我们深入讲解了链表的内容,这一章,我们详细介绍一种较为简单的数据结构———栈。 首先,我们介绍栈是什么:栈是一种单向的结构,其中栈的底部是固定的,不可以进出,我们可操作的部分只有栈顶,来进行出入栈操作。...
2
数据结构之树及树的存储
数据结构 ——————————————本栏目旨在交流计算机知识————————————————— 上一章节,我们介绍了线性的数据结构:表,栈,队列。接下来,我们将进入下一章节——树结构的学习。 首先,我们先介绍一下树的基本概念: 结点:使⽤树结构存储的每一个数据元素都被称为“结点”。例如图中的A就是一个结点。...
3
数据结构二叉树的基本介绍
数据结构 ————————————本文旨在讨论与学习计算机知识,欢迎交流———————————— 上一章,我们讲解了树结构的综述导论,那么,现在我们来深入了解一下树结构中最常用研究的结构——二叉树结构(上一章的扩展——孩子兄弟表示法就是利用的二叉树的原理)。 以上是关于普通二叉树的基本概念,我们可以结合上一...
4
数据结构深度搜索与广度搜索的概念
数据结构 ————————————本文旨在交流计算机知识,欢迎指正!———————————— 上一章节我们系统介绍了树的存储结构与基本概念,这一章,我们将详细介绍一下——树的基本应用。首先,笔者会介绍树的基本遍历模式,其次,我会详细讲解深度优先搜索和广度优先搜索的概念。 首先,我们来介绍一下树的几种遍历形式:...
5
顺序表的实现与介绍及部分工程思想的思考
数据结构 ——————————本文旨在讨论和探究计算机知识,欢迎指正———————————— 首先,我们来聊聊什么是线性表: 线性表,顾名思义,是一种具有线性结构的数据排布形式 ,是一个类似数组的东西,在逻辑上一个接一个有序的整块链接,区别于链表的无序分布链接。 如图,我们可以得出,顺序表是一条线一样的结构...
随机文章 随机推荐
Profile Image of the Author
Firefly
Hello, I'm Firefly.
公告
欢迎来到我的博客!这是一则示例公告。
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
33
分类
7
标签
25
总字数
56,127
运行时长
0
最后活动
0 天前
站点信息
构建平台
Vercel
博客版本
Firefly v6.12.3
文章许可
CC BY-NC-SA 4.0

文章目录