【数据结构】队列的实现(链式)

文章目录

  • 队列
    • 1.队列的概念及结构
      • 概念
      • 结构
    • 2.队列的实现(链式结构)
      • 队列定义
      • 初始化队列
      • 入队
      • 出队
      • 获取队头元素
      • 获取队尾元素
      • 销毁队列
      • 判断队列是否为空
      • 队列有效个数
    • 完整代码(包含测试代码)
      • Queue.h
      • Queue.c
      • test.c

队列

1.队列的概念及结构

概念

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表。
队列具有先进先出FIFO(First In First Out)
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头在这里插入图片描述

结构

队列也可以数组和链表的结构实现:

队列的顺序结构
入队,直接下标访问,时间复杂度为O(1)
出队,挪动数据覆盖,时间复杂度为O(N)

队列的链式结构
定义两个指针,队头指针指向第一个节点,队尾指针指向尾节点
入队(尾插),时间复杂度为O(1)
出队(头删),时间复杂度为O(1)

所以使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
在这里插入图片描述

2.队列的实现(链式结构)

首先新建一个工程:

Queue.h(队列的类型定义、接口函数声明、引用的头文件)
Queue.c(队列接口函数的实现)
test.c(主函数、测试栈各个接口功能)

完整的代码放在后面(包括测试代码),这里就不会展示测试的效果图。大家可以自己别敲边按测试代码测试。图解会写的很详细的,么么😙

队列定义

typedef int QDataType;//队列结点结构
typedef struct QlistNode 
{QDataType val;//结点元素struct QlistNode* next;//结点指针
}QNode;//队列链式结构
typedef struct Queue
{QNode* phead;//队头指针QNode* ptail;//队尾指针int size;//元素个数
}Queue;

初始化队列

初始化这里很讲究的,如果不把两个指针放到结构体里面封装起来,单独来传,那这里很麻烦要用二级指针而且也不太好控制,但是如果用结构体封装起来我们访问这两指针就是访问结构体的成员,要修改就直接修改指向结构体的指针pq就ok了
我们链表那里就讲过了传参的问题,我们实现无头链表的头插头删接口时,因为需要改变头指针的指向两种方法:
1、传二级指针
2、返回值(return)
现在又有了一种方法:
结构体封装起来

//初始化队列
void QueueInit(Queue* pq)
{assert(pq);pq->phead = NULL;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->val = x;newnode->next = NULL;if (pq->phead==NULL)//队列为空插入{pq->phead = pq->ptail = newnode;}else//队列有元素{pq->ptail->next = newnode;pq->ptail = newnode;}pq->size++;
}

出队

这个也就是链表的头删

//出队
void QueuePop(Queue* pq)
{assert(pq);assert(pq->phead);//队列不能为空if (pq->phead->next==NULL)//队列只有一个元素{pq->ptail = NULL;}QNode* del = pq->phead;pq->phead = pq->phead->next;free(del);del = NULL;pq->size--;}

获取队头元素

//获取队头元素
QDataType QueueFront(Queue* pq)
{assert(pq);assert(pq->phead);//队列不能为空return pq->phead->val;
}

获取队尾元素

//获取队尾元素
QDataType QueueBack(Queue* pq)
{assert(pq);assert(pq->ptail);//队列不能为空return pq->ptail->val;
}

销毁队列

//销毁队列
void QueueDestroy(Queue* pq)
{assert(pq);QNode* pcur = pq->phead;while (pcur){QNode* next = pcur->next;free(pcur);pcur = next;}pcur = NULL;pq->phead = NULL;pq->ptail = NULL;pq->size = 0;
}

判断队列是否为空

//判断队列是否为空
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->phead == NULL;//pq->phead、pq->ptail两个用哪一个都行
}

队列有效个数

//队列有效个数
int QueueSize(Queue* pq)
{assert(pq);return pq->size;}

完整代码(包含测试代码)

Queue.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int QDataType;//队列结点结构
typedef struct QlistNode 
{QDataType val;//结点元素struct QlistNode* next;//结点指针
}QNode;//队列链式结构
typedef struct Queue
{QNode* phead;//队头指针QNode* ptail;//队尾指针int size;//元素个数
}Queue;//初始化队列
void QueueInit(Queue* pq);
//入队
void QueuePush(Queue* pq, QDataType x);
//出队
void QueuePop(Queue* pq);
//获取队头元素
QDataType QueueFront(Queue* pq);
//获取队尾元素
QDataType QueueBack(Queue* pq);
//销毁队列
void QueueDestroy(Queue* pq);
//判断队列是否为空
bool QueueEmpty(Queue* pq);
//队列有效个数
int QueueSize(Queue* pq);

Queue.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"queue.h"//初始化队列
void QueueInit(Queue* pq)
{assert(pq);pq->phead = NULL;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->val = x;newnode->next = NULL;if (pq->phead==NULL)//队列为空插入{pq->phead = pq->ptail = newnode;}else//队列有元素{pq->ptail->next = newnode;pq->ptail = newnode;}pq->size++;
}
//出队
void QueuePop(Queue* pq)
{assert(pq);assert(pq->phead);//队列为空中止if (pq->phead->next==NULL)//队列只有一个元素{pq->ptail = NULL;}QNode* del = pq->phead;pq->phead = pq->phead->next;free(del);del = NULL;pq->size--;}
//获取队头元素
QDataType QueueFront(Queue* pq)
{assert(pq);assert(pq->phead);return pq->phead->val;
}
//获取队尾元素
QDataType QueueBack(Queue* pq)
{assert(pq);assert(pq->ptail);return pq->ptail->val;
}
//销毁队列
void QueueDestroy(Queue* pq)
{assert(pq);QNode* pcur = pq->phead;while (pcur){QNode* next = pcur->next;free(pcur);pcur = next;}pcur = NULL;pq->phead = NULL;pq->ptail = NULL;pq->size = 0;
}
//判断队列是否为空
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->phead == NULL;
}
//队列有效个数
int QueueSize(Queue* pq)
{assert(pq);return pq->size;}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"int main()
{Queue Q;QueueInit(&Q);QueuePush(&Q, 1);QueuePush(&Q, 2);QueuePush(&Q, 3);QueuePush(&Q, 4);QueuePush(&Q, 5);//打印队列//while (!QueueEmpty(&Q))//{//	printf("%d ", QueueFront(&Q));//	QueuePop(&Q);//}//printf("\n");int r = QueueSize(&Q);printf("%d ", r);//printf("%d ", QueueBack(&Q));return 0;
}

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

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

相关文章

(毫米波雷达数据处理中的)聚类算法(2) – DBSCAN算法及其实践

说明 读者在阅读本文前&#xff0c;建议先看看本系列的第一篇文章&#xff1a;[1]&#xff08;毫米波雷达数据处理中的&#xff09;聚类算法(1) --- 概述-CSDN博客 DBSCAN算法(Density-Based Spatial Clustering of Applications With Noise)是一种基于密度的聚类算法&#xff…

程序设计:控制台输出二叉树 二叉树的形象显示

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 本文指导你编写一个输出到字符…

lerna实战(一)

前言 将大型代码仓库分割成多个独立版本化的 软件包&#xff08;package&#xff09;对于代码共享来说非常有用。但是&#xff0c;如果某些更改 跨越了多个代码仓库的话将变得很 麻烦 并且难以跟踪&#xff0c;并且&#xff0c; 跨越多个代码仓库的测试将迅速变得非常复杂。 …

Android Q - 音频通路调试

对于当前模块不是很清楚&#xff0c;刚好有个项目这方面有点问题&#xff0c;根据展锐支持文档一步步检查就可以了。首先得先弄清楚硬件具体是怎么连接的&#xff0c;比如文档提到的案例&#xff1a;sprd codec speaker output 连接外部 PA。 耳机接的是什么&#xff0c;speake…

Java线程生命周期:Java线程生命周期全景解读

1. 线程生命周期概述&#xff1a;不仅仅是状态转换 在多线程编程中&#xff0c;理解线程的生命周期对于编写有效、高效的代码至关重要。线程生命周期通常描述了线程从创建到死亡的一系列状态变化过程&#xff0c;但其实不仅仅局限于这些状态的简单转换。线程生命周期的理解应该…

Redis的集群模式——Java全栈知识(20)

1、主从模式 Redis 支持主从模式的集群搭建&#xff0c;这是 Redis 提供的最简单的集群模式搭建方案&#xff0c;目的是解决单点服务器宕机的问题。当单点服务器发生故障的时候保证 Redis 正常运行。 主从模式主要是将集群中的 Redis 节点分为主节点和从节点。然后读和写发生在…

buff禁售武器箱和胶囊的原因,及游戏搬砖人该如何应对

大家好&#xff0c;我是童话&#xff0c;相信大家都看到这个消息了&#xff0c;buff平台在14号中午11点左右&#xff0c;已经全面禁止了武器箱和胶囊&#xff0c;纪念包等的上架和售卖。在饰品市场直接搜索武器箱或者胶囊&#xff0c;是完全搜索不出来任何东西的哈。 面对这一消…

平衡三进制小数详解与进制转换

标准三进制是“逢三进一&#xff0c;退一还三”的机制&#xff0c;平衡三进制与之类似&#xff0c;但就是偏移了一下变得对称了&#xff0c;平衡三进制是逢/-2进1或进T的&#xff0c;平衡三进制与标准三进制可以相互转换&#xff0c;但这样显得有点多余了&#xff0c;所以这里只…

Nginx 7层负载均衡的搭建

目录 负载均衡的理解 修改配置文件 测试 1. 选择在 DMZ 区测试&#xff0c;使用 db 服务器进行测试 2.选择在外网测试负载均衡效果 负载均衡的理解 负载均衡&#xff1a;load balancer&#xff0c;简称LB Nginx 既是一个 web 服务器软件&#xff0c;也是一个负载均衡软件&a…

谷歌I/O 2024大会全面硬刚OpenAI

&#x1f989; AI新闻 &#x1f680; 谷歌发布升级版Gemini机器人 竞争OpenAI ChatGPT-4 摘要&#xff1a;谷歌展示了升级版的 Gemini 聊天机器人&#xff0c;其支持实时处理视频和语音输入&#xff0c;并准确回答问题。此次发布时机与 OpenAI 公布 ChatGPT-4o 新模型几乎同步…

在浏览器执行js脚本的两种方式

fetch请求get 在浏览器执行http请求,可以使用fetch函数; fetch(“url”).then(response => response.text()) .then(data => console.log(JSON.parse(data)[‘status’])) .catch(error => console.error(error)) 直接返回json数据: fetch(“url”).then(response…