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

【数据结构】栈和队列(下)

目录

一、队列(先进先出的特殊结构)

队列的概念与结构

二、代码实现

1、定义队列的结构

2、队列的初始化操作

3、判空操作

4、入队操作

5、出队操作

6、取队头、队尾操作

7、队列销毁操作

8、队列中有效数据个数

9、测试代码

10、.h文件


一、队列(先进先出的特殊结构)

队列的概念与结构

队列:只允许在一端进行插入数据数据操作,在另一端进行删除数据的特殊线性表,队列具有先进先出的结构

同栈一样,我们先来讨论一下队列的底层结构该如何选型?

首先我们来看一下数组的结构,如果将数组当做队列底层的结构,那么入队列操作的时间复杂度为O(1),由于出队列操作,数组要删除头部的数据,那么数组头部之后的数据就要整体向前挪动一位,所以出队列的时间复杂度为O(N);若将队尾与队头对调,他们的时间复杂度将对调。

其次,我们来考虑链表结构,以单链表为例,假设链表的头为队头,链表的尾为队尾,队头用来出数据,时间复杂度为O(1),队尾用来入数据,由于每次入数据都要遍历找到尾结点,所以时间复杂度为O(N),如果将队头队尾对调,他们的时间复杂度也将对调。

那么,既然这样,我们就要想一些法子,来减少时间复杂度:

如果用双向链表可不可行呢?这个问题值得思考,假设使用双向链表,对头的prev指针指向队尾,但是每一个结点除去原有的数据,还要存储两个指针类型的数据,如果是32字节的系统,假设是整型数据,int类型数据占4个字节,两个地址占4*2=8字节,4+8=12字节,考虑内存对齐,共消耗了16字节的空间,这个数据过于庞大,所以我们不再考虑双向链表。

下面,我们考虑优化链表的时间复杂度来实现队列的底层结构。

如果是链表头结点为队头,即入队时间复杂度为O(1),出队时间复杂度为O(N)的情况,我们可以用定义两个指针,分别记录队头和队尾:phead、ptail,来将出队操作的时间复杂度降为O(1)。

从此处我们可以得出一个结论,队列的逻辑结构是线性的,而物理结构不一定是线性的。

二、代码实现

下面,我们来准备一下队列的代码实现:

1、定义队列的结构

//定义结点的结构
typedef int QueueDataType;
typedef struct QueueNode
{QueueDataType data;struct QueueNode* next;
}QueueNode;//定义队列的结构
typedef struct Queue
{QueueNode* phead;QueueNode* ptail;
}Queue;

2、队列的初始化操作

Void QueueInit(Queue*pq)
{assert(pq);pq->phead = pq->ptail = NULL;
}

3、判空操作

bool QueueEmpty(Queue*pq)
{assert(pq);return pq->phead == NULL;
}

4、入队操作

Void QueuePush(Queue* pq,QueueDataType x)
{assert(pq);QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueDataType));if(newnode == NULL){perror("malloc failed!");exit(1);}newnode->data = x;newnode->next = NULL;if(QueueEmpty(pq))//考虑队列为空的情况{pq->phead = pq->ptail = newnode;}else{//队列非空pq->ptail->next = newnode;pq->ptail = pq->ptail->next;}
}

5、出队操作

void QueuePop(Queue* pq)
{assert(!QueueEmpty(pq));if(pq->phead == pq->ptail){//只有一个结点free(pq->phead);pq->phead = pq->ptail = NULL;   }else{QueueNode* next = pq->phead->next;free(pq->phead);pq->phead = next;}
}

6、取队头、队尾操作

//取队头
QueueDataType QueueFront(Queue* pq)
{assert(pq);return pq->phead->data;
}
//取队尾
QueueDataType QueueBack(Queue* pq)
{assert(pq);return pq->ptail->data;
}

7、队列销毁操作

//销毁队列
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;
}

8、队列中有效数据个数

//队列有效数据个数
int QueueSize(Queue* pq)
{assert(pq);QueueNode* pcur = pq->phead;int size = 0;while (pcur){size++;pcur = pcur->next;}return size;
}

这里的时间复杂度为O(N),仅适用于不频繁调用有效数据个数的情况,如果想优化这则代码,我们可以在对列中定义一个整型的size,如果写了size,那么我们在入队列时,size要++,出队列时,size要--,销毁时,size要置为0。

9、测试代码

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

10、.h文件

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>//定义结点的结构
typedef int QueueDataType;
typedef struct QueueNode
{QueueDataType data;struct QueueNode* next;
}QueueNode;//定义队列的结构
typedef struct Queue
{QueueNode* phead;QueueNode* ptail;//int size;
}Queue;//队列的初始化
void QueueInit(Queue* q);//入队,队尾
void QueuePush(Queue* pq, QueueDataType x);//出队,队头
void QueuePop(Queue* pq);//取队头操作
QueueDataType QueueFront(Queue* pq);//取队尾操作
QueueDataType QueueBack(Queue* pq);//销毁队列
void QueueDestory(Queue* pq);//有限数据个数
int QueueSize(Queue* pq);

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

相关文章:

  • python打卡day39@浙大疏锦行
  • vite配置一个css插件
  • MySQL字段为什么要求定义为not null ?
  • 约瑟夫问题
  • insightface==0.7.3 编译失败
  • 从时钟精度看晶振频率稳定度的重要性
  • 12-后端Web实战(登录认证)
  • 实验设计与分析(第6版,Montgomery)第5章析因设计引导5.7节思考题5.4 R语言解题
  • Linux文件操作、文件夹操作
  • 【前端】使用grid布局封装断点式进度条
  • Flannel 支持的后端
  • 交集、差集、反选
  • 蓝牙和wifi相关的杂项内容总结
  • Executors面试题
  • apptrace 的优势以及对 App 的价值
  • 【Stable Diffusion 1.5 】在 Unet 中每个 Cross Attention 块中的张量变化过程
  • 磁盘管理无法删除卷,虚拟磁盘管理器:不支持该请求
  • Attention Is All You Need论文阅读笔记
  • Wirtinger Flow算法的matlab实现和python实现
  • 【前端】Twemoji(Twitter Emoji)
  • RV1126-OPENCV Mat理解
  • 某东 h5st第8个参数 指纹加密纯算解析
  • 模型微调之对齐微调KTO
  • MySQL的binlog有有几种录入格式分别有什么区别 ?
  • VSCode的下载与安装(2025亲测有效)
  • LLaMaFactory 微调QwenCoder模型
  • Windows 中禁止在桌面放置文件以保持桌面整洁
  • 深入详解编译与链接:翻译环境和运行环境,翻译环境:预编译+编译+汇编+链接,运行环境
  • does not provide an export named ‘getActiveHead‘
  • 集成均衡功能电池保护芯片在大功率移动电源的应用,创芯微CM1341-DAT、杰华特JW3312、赛微微电CW1244、中颖SH366006