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

news2024/9/25 11:17:49

文章目录

  • 队列
    • 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.coloradmin.cn/o/1677588.html

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

相关文章

nodemon运行ts文件

https://juejin.cn/post/7035637086451400734 nodemon经常用来调试js文件&#xff0c;大家都是知道的&#xff0c;但是用nodemon来调试ts文件&#xff0c;大家试过吗&#xff1f; 如果直接运行nodemon index.ts是会报错的。 ts 复制代码 //index.ts console.log(1) 需要全局…

安全设备篇——抗DDOS设备

写在前面&#xff1a;up初研究这个设备的时候以为很容易&#xff0c;毕竟ddos嘛大家都懂&#xff0c;但是实际去找资料和研究的时候发现资料少的可怜&#xff0c;再加上大家知道ddos但大多没见过&#xff0c;万幸up的老东家某普有这类设备&#xff0c;和之前的同事沟通了一下还…

百望云钉钉:重塑财务智能化管理,助力企业实现数字化飞跃

近年来&#xff0c;数字技术正在深刻改变着企业生产方式和组织模式&#xff0c;企业面连着业务流程再造、经营模式创新等一系列建设挑战。 其中&#xff0c;财务部门从价值守护走向价值创造的过程中&#xff0c;展现出对企业经营与业务发展的巨大影响力。叠加金税四期税务改革&…

【稳定检索|主题广泛】2024年人文发展、媒体传播与文化交流国际会议(DMCCE 2024)

2024年人文发展、媒体传播与文化交流国际会议&#xff08;DMCCE 2024&#xff09; 2024 International Conference on Cultural Development, Media Communication, and Cultural Exchange 【会议简介】 2024年人文发展、媒体传播与文化交流国际会议将于成都举行。此次会议将…

计算机考研|408备考,如何6个月顺利上岸?经验+资料分享

如果是跨考的话&#xff0c;现在已经快六月份了&#xff0c;备考408时间真的很紧张 u1s1&#xff0c;我虽然一直推荐大家考408&#xff0c;但是也看情况&#xff0c;这种跨考&#xff0c;并且时间不充足的情况下&#xff0c;就最好不要去硬刚408了。408的复习量很大&#xff0…

【python数据预处理系列】使用Pandas的factorize()函数进行类别编码(整数编码)

在Pandas中&#xff0c;factorize()函数主要用于将分类变量转换为整数编码&#xff0c;这对于减少内存使用或准备数据进行某些统计分析非常有用。 它实际上是将列的唯一值映射到从0开始的整数序列上。 假设有一个DataFrame&#xff0c;其中一列包含一些类别值&#xff0c;你希望…

运筹说 第114期 | 其他排队模型简介

前面我们已经学习了一些排队模型&#xff0c;对排队系统有了基本认知&#xff0c;本期小编带大家继续来学习其他排队模型的内容。 一、有限源排队模型 顾客源为有限的这类排队问题的主要特征是顾客总数是有限的&#xff0c;如只有m个顾客。每个顾客来到系统中接受服务后仍回到…

jmeter指南:JMeter 安装、配置和性能测试

使用 JMeter 进行性能测试 1. Java 版本要求 JMeter 要求与 Java 8 或更高版本兼容。为了确保安全性和性能&#xff0c;建议安装最新次要版本的主要 Java 版本。鉴于 JMeter 仅使用标准 Java API&#xff0c;如果由于 JRE 实现问题而无法运行 JMeter&#xff0c;请不要提交错…

为Akamai 云平台上部署的资源配置2FA跳板机-上

为重要账户启用2FA&#xff0c;这几乎已经成为保护账户和数据安全的一种标准做法。无论登录常见应用或服务&#xff0c;或是访问企业内部资源&#xff0c;时不时都会需要进行2FA验证。那么当你在Akamai Connected Cloud云平台中部署了各类资源&#xff08;云计算、云存储、SaaS…

Java面试八股之float和double的区别

Java中float和double的区别 存储空间与精度&#xff1a; double&#xff1a;占据64位&#xff08;8字节&#xff09;存储空间&#xff0c;属于双精度浮点数。它可以提供较高的精度&#xff0c;通常能够精确表示大约15到17位十进制数字&#xff0c;适合用于需要较高精度计算或…

【面试必看】MyBatis部分

MyBatis 必读 Mybatis系列全解 MyBatis最全使用指南 MyBatis最全使用指南 1. JDBC java 操作数据库的原始方式就是 JDBC。 但是存在以下问题&#xff1a; 每次操作我们都要创建 connection、Statement 等一些对象&#xff0c;操作完还要关闭、销毁这些对象。 ResultSet …

【OSM】RDP资源无法访问

发布windows的远程桌面资源&#xff0c;web和rdp方式都不能访问&#xff0c;端口测试都正常&#xff0c;不经过堡垒机能正常连接服务器 1、将资源中rdp安全模式指定为rdp&#xff0c;并直接登录到服务器&#xff0c;打开【组策略】&#xff0c;依次展开计算机配置→Windows组件…

手撸XXL-JOB(四)——远程调用定时任务

Java Socket网络编程 网络编程是Java编程中的重要组成部分&#xff0c;包括服务端和客户端两部分内容。Socket是Java网络编程的基本组件之一&#xff0c;用于在应用程序之间提供双向通信&#xff0c;Socket提供了一种标准的接口&#xff0c;允许应用程序通过网络发送和接收数据…

分体工业读写器的适用场景有哪些?

工业读写器根据设计方式不同&#xff0c;可分为一体式读写器和分体式读写器&#xff0c;不同读写器特点不同&#xff0c;适用场景也不同&#xff0c;下面我们就一起来了解一下超高频分体读写器适用场景有哪些。 超高频分体读写器介绍 超高频分体读写器是一种射频识别(RFID)设…

SpringAI应用开发

一、人工智能简述 四次工业革命推动了人类社会发展和变革&#xff1a; 蒸汽时代&#xff0c;发生在18世纪60年代~19世纪中期&#xff08;大约是1760年到1860年&#xff09;&#xff0c;这一时期的特点是机械化生产和大规模生产。电气时代&#xff0c;发生在19世纪下半叶~20世纪…

一篇文章搞懂 SDN中Minint和Ryu的安装及使用

SDN 一、SDN介绍 一&#xff0e; 什么是SDN? SDN字面意思是软件定义网络&#xff0c;其试图摆脱硬件对网络架构的限制&#xff0c;这样便可以像升级、安装软件一样对网络进行修改&#xff0c;便于更多的APP&#xff08;应用程序&#xff09;能够快速部署到网络上。 如果把…

pcdn边缘云常见sla有哪些?如何避免被白嫖

PCDN&#xff08;Point-to-Point Content Delivery Network&#xff09;边缘云常见的SLA&#xff08;Service Level Agreement&#xff09;规则包括高峰期离线、服务时间、重传延时、限速等。这些规则是为了保证服务质量和用户体验。下面将详细解释这些规则&#xff0c;并提供一…

51单片机:点亮一个LED灯

1.新建工程 选择AT89C52&#xff0c;在Atmel下显示的是See Microchip 并不需要添加启动文件到文件夹中。 添加main.c文件&#xff0c;c比cpp效率高&#xff0c;.asm汇编即更底层 程序编写好后 nop(); 该函数在这个头文件里面 #include <INTRINS.H> #include <R…

flex 盒子布局 align-items: start; flex-wrap: wrap; justify-content: space-between;

flex 盒子布局 align-items: start; flex-wrap: wrap; justify-content: space-between; 总盒子 .allboc {display: flex;width: 100%;align-items: start;flex-wrap: wrap;justify-content: space-between; }左边 justify-content: flex-start; .blog-articles {display: fl…

3588 pwm android12 的操作,包含 NDK native C++

问题&#xff1a; 客户需要在android12 的界面上操作板卡上的 PWM 蜂鸣器设备。 过程&#xff1a; 1 了解一下 3588 android12 源码的 关于PWM 的驱动。 设备树找不到 pwm 但是&#xff0c; 还不知道&#xff0c;android12 最终包含的 设备树是哪个&#xff0c;但是经过我的…