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

数据结构之队列:初始化、入队、出队与源码全解析

目录

  • 前言
  • 一、队列
    • 1.1 概念与结构
    • 1.2 队列的实现
      • 1.2.1 初始化
      • 1.2.2 入队--队尾
      • 1.2.3 判断队列是否为空
      • 1.2.4 出队--对头
      • 1.2.5 取对头和取队尾
      • 1.2.6 队列中有效元素个数
      • 1.2.7 销毁队列
  • 二、队列完整源码
  • 结语

在这里插入图片描述

在这里插入图片描述

🎬 云泽Q:个人主页

🔥 专栏传送入口: 《C语言》《数据结构》《C++》《Linux》

⛺️遇见安然遇见你,不负代码不负卿~

前言

大家好啊,我是云泽Q,一名热爱计算机技术的在校大学生。近几年人工智能技术飞速发展,为了帮助大家更好地抓住这波浪潮,在开始正文之前,我想先为大家推荐一个非常优质的人工智能学习网站)。它提供了从基础到前沿的系列课程和实战项目,非常适合想要系统入门和提升AI技术的朋友,相信能对你的学习之路有所帮助。

一、队列

1.1 概念与结构

概念:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)的性质
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
在这里插入图片描述
队列如果使用数组结构的话,头部的插入删除时间复杂就是O(n)
在这里插入图片描述
队列遵循 “先进先出”(FIFO)原则,通常需要两个指针(或索引):
一个指向队头(front),表示下一个要出队的元素
一个指向队尾(rear),表示下一个要入队的位置
出队操作:当队头元素被移除后,front 指针需要后移。此时如果要保持队列元素的连续性(让新的队头元素位于数组起始位置),就需要将所有剩余元素向前移动一位,这个操作的时间复杂度是 O (n),队尾插入数据时间复杂度为O(1)

若使用单链表来实现,尾插就要找尾节点,插入数据时间复杂度为O(n),删除数据时间复杂度为O(1)

虽然双向链表不论头尾,所有位置的操作时间复杂度都为O(1),但是单链表在结构体当中只有两个成员,占用8个字节,但是双向链表有三个成员,再加上内存对齐,空间会更大,所以一般情况下并不会使用双向链表

但是单链表的插入数据的时间复杂度还可以优化,删除数据是队头的操作,时间复杂度为O(1),可以让phead指针始终指向队列的头,只额外增加一个ptail指针指向尾节点,此时增加的成本也不高,插入数据的时间复杂度就为O(1)了

所以说这里用链表来实现队列更好一些

在整个队列结构,只用关心头尾的两个指针,由于这两个指针指向的是队列中的节点,所以两个指针是节点数据类型

//节点的结构
struct ListNode
{int data;struct ListNode* next;
}
//队列的结构
struct Queue
{struct ListNode* phead;//指向队头节点的指针struct ListNode* ptail;//指向队尾节点的指针
}

稍做优化

typedef int QDataType;
//定义节点结构
typedef struct QueueNode
{QDataType data;struct QueueNode* next;
}QueueNode;
//定义队列结构
typedef struct Queue
{QueueNode* phead;//对头QueueNode* ptail;//队尾
}Queue;

1.2 队列的实现

1.2.1 初始化

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.2.2 入队–队尾

这里分两种情况
第一种情况就是队列不为空
在这里插入图片描述
在这里插入图片描述

第二种情况就是队列为空
在这里插入图片描述
在这里插入图片描述

//入队--队尾
void QueuePush(Queue* pq, QDataType x);

在这里插入图片描述
在这里插入图片描述

1.2.3 判断队列是否为空

//判断队列是否为空
bool QueueEmpty(Queue* pq);

在这里插入图片描述

1.2.4 出队–对头

这里也分两种情况
第一种情况队列中大于等于2个节点
在这里插入图片描述
在这里插入图片描述

第二种情况队列只有一个节点
在这里插入图片描述
此时next指向为空,头节点free掉之后,phead指向next指针指向的节点,但是此时ptail就是野指针了

//出队--对头
void QueuePop(Queue* pq);

在这里插入图片描述
在这里插入图片描述

1.2.5 取对头和取队尾

//取对头数据
QDataType QueueFront(Queue* pq);
//取队尾数据
QDataType QueueBack(Queue* pq);

在这里插入图片描述
在这里插入图片描述

1.2.6 队列中有效元素个数

//队列中有效元素个数
int QueueSize(Queue* pq);

在这里插入图片描述
在这里插入图片描述
但是这个方法的时间复杂度为O(n),还有优化方案,就是在队列的结构体多定义一个成员size,初始化size=0,入队列加加,出队列减减,这样计算有效元素个数方式时间复杂度就为O(1)

1.2.7 销毁队列

队列的销毁就是单链表的销毁
在这里插入图片描述
只要pcur不为空,就把下一个节点存起来,然后将pcur指向的节点销毁,然后pcur指向next指向的节点
在这里插入图片描述
如果此时pcur指向的节点不为空,先让next指针指向下一个待删除的节点,再将pcur销毁,循环往复
在这里插入图片描述
pcur为空,队列销毁完成

//销毁队列
void QueueDestory(Queue* pq);

在这里插入图片描述

二、队列完整源码

Queue.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int QDataType;
//定义节点结构
typedef struct QueueNode
{QDataType data;struct QueueNode* next;
}QueueNode;
//定义队列结构
typedef struct Queue
{QueueNode* phead;//队头QueueNode* ptail;//队尾//int size;        //队列中有效元素个数
}Queue;//初始化
void QueueInit(Queue* pq);
//入队--队尾
void QueuePush(Queue* pq, QDataType x);
//判断队列是否为空
bool QueueEmpty(Queue* pq);
//出队--对头
void QueuePop(Queue* pq);
//取对头数据
QDataType QueueFront(Queue* pq);
//取队尾数据
QDataType QueueBack(Queue* pq);
//队列中有效元素个数
int QueueSize(Queue* pq);
//销毁队列
void QueueDestory(Queue* pq);

Queue.c

#define _CRT_SECURE_NO_WARNINGS
#include"Queue.h"//初始化
void QueueInit(Queue* pq)
{assert(pq);pq->phead = pq->ptail = NULL;//pq->size = 0;
}//入队--队尾
void QueuePush(Queue* pq, QDataType x)
{assert(pq);QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));if (newnode == NULL){perror("malloc fail!");exit(1);}newnode->data = x;newnode->next = NULL;if (pq->phead == NULL){pq->phead = pq->ptail = newnode;//pq->size++;}else {pq->ptail->next = newnode;pq->ptail = pq->ptail->next;//pq->size++;}
}//判断队列是否为空
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->phead == NULL;
}//出队--对头
void QueuePop(Queue* pq)
{assert(!QueueEmpty(pq));if (pq->phead == pq->ptail){free(pq->phead);pq->phead = pq->ptail = NULL;//pq->size--;}else {QueueNode* next = pq->phead->next;free(pq->phead);pq->phead = next;//pq->size--;}
}//取对头数据
QDataType QueueFront(Queue* pq)
{assert(!QueueEmpty(pq));return pq->phead->data;
}//取队尾数据
QDataType QueueBack(Queue* pq)
{assert(!QueueEmpty(pq));return pq->ptail->data;
}//队列中有效元素个数
int QueueSize(Queue* pq)
{assert(pq);QueueNode* pcur = pq->phead;int size = 0;while (pcur){++size;pcur = pcur->next;}return size;//return pq->size;
}//销毁队列
void QueueDestory(Queue* pq)
{assert(pq);QueueNode* pcur = pq->phead;while (pcur){QueueNode* next = pcur->next;free(pcur);pcur = next;}pq->phead = pq->ptail = NULL;
}

test.c

#define _CRT_SECURE_NO_WARNINGS
#include"Queue.h"void test01()
{Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);//QueuePop(&q);//QueuePop(&q);//QueuePop(&q);//QueuePop(&q);//printf("队头:%d\n", QueueFront(&q));//printf("队尾:%d\n", QueueBack(&q));//printf("size:%d\n", QueueSize(&q));QueueDestory(&q);
}int main()
{test01();return 0;
}

结语

在这里插入图片描述

http://www.dtcms.com/a/438292.html

相关文章:

  • 国内外优秀网站网站建设江苏百拓
  • hive、spark任务报错或者异常怎么排查以及定位哪段sql
  • 南昌商城网站设计洛阳青峰网络做网站
  • 算法 - FOC闭环位置控制
  • 探索高效安全的去中心化应用——Solana区块链
  • 大模型openai服务网关,认证,限流,接口输入输出的修正,监控等功能
  • 贵州百度seo整站优化做网站收入怎样
  • AI驱动的视频生成革命:MoneyPrinterTurbo技术架构深度解析
  • 东莞p2p网站开发价钱店铺logo在线制作免费
  • LeetCode:89.分割等和子集
  • 基于 GEE 处理、可视化和导出 Landsat 5 和 Landsat 8 卫星遥感影像数据
  • Python基础入门例程88-NP88 句子拆分
  • 网站上添加图片的原则59网一起做网站
  • k8s学习(一)——kubernetes重要基础概念概述
  • Unity excel 表格文件导入
  • 【系统架构设计-零】系统架构设计总述与学习线路
  • 做网站郑州公司北京工商局网站如何做股东变更
  • 【C++】C++ 中多态是什么?咋用的?
  • Dijkstra最短路径算法
  • 扶沟县网站开发怎么知道一个网站是哪家公司做的
  • mysql基于GTID恢复数据
  • LabVIEW正弦波去噪与信号处理
  • winform 五子棋
  • Java实现BCH与BTC的地址相互转换
  • CyberSecurity:SSL Client-Initiated Renegotiation 客户端发起的重新协商ddos攻击
  • 关于Mybatis-Plus的insertOrUpdate()方法使用时的问题与解决—数值精度转化问题
  • 石家庄做网站制作公司网站写作赚钱
  • Docker、容器、虚拟机到底是什么
  • 西安微信商城网站开发做阿里巴巴怎么进公司网站
  • Go语言入门(17)-接口