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

【数据结构】_队列的结构与实现

目录

1. 队列的概念和结构

2. 队列的应用

3. 队列的实现

3.1 队列实现的底层结构选择

3.2 结构体设计

3.2.1 仅为链表结点设计结构体

3.2.2 为链表再设计一个结构体

3.3 Queue.h

3.4 Queue.c

3.5 Test_Queue.c

注:部分方法实现细节


1. 队列的概念和结构

队列:只允许在一端进行数据的插入操作,在另一端进行数据的删除操作的特殊线性表,队列具有先进先出FIFO(First In First Out)的特点。

入队列:进行插入操作的一端称为队尾;

出队列:进行删除操作的一端称为队头;(尾进头出)

2. 队列的应用

队列的最大特点是保持公平性。其主要应用场景有以下两个:

(1)设置排队器:实现先进先出;

(2)实现二叉树的广度优先遍历;

3. 队列的实现

3.1 队列实现的底层结构选择

1、若采用数组实现:

若将数组头视为队头,数组尾视为队尾,则插入对应尾插实现方便,但删除对应头删实现麻烦;

若将数组头视为队尾,数组尾视为队头,则删除对应尾删实现方便,但插入对应头插实现麻烦;

选数组实现队列则不便实现。

2、若采用单链表实现:(采用此种结构)

(相较于双链表,单链表更节省空间)

链表尾视为队尾,链表头视为队头

则插入对应尾插实现方便(记录尾结点可避免遍历),删除对应头删也实现方便。

3.2 结构体设计

采用单链表结构实现队列,则结点包括数据域val和后继指针域next两个成员。

且队列的插入通过链表尾插实现,为了避免每次插入都需遍历链表,采取插入传参尾结点的方式;

3.2.1 仅为链表结点设计结构体

以插入和删除操作为例,都有可能造成第一个结点指针和尾结点指针的变化,故需传二级指针:

typedef int QDataType;
typedef struct QueueNode {QDataType val;struct QueueNode* next;
}QNode;
// 队尾插入
void QueuePush(QNode** pphead, QNode** pptail, QDataType x);
// 队头删除
void QueuePop(QNode** pphead, QNode** pptail);

注:若采取设有头结点的单链表,可传一级指针,但仍然需传队尾结点指针,仍需要传递两个参数,总体而言依然较为麻烦。 

3.2.2 为链表再设计一个结构体

由于插入删除操作均需队头指针与队尾指针,可为其再设置一个结构体。

同时考虑:由于需要提供返回队列元素个数的方法,若在该方法内部对单链表进行遍历,则该方法时间复杂度为O(N),可以在Queue结构体内再设置一个变量size以计算队列元素个数:

typedef int QDataType;
typedef struct QueueNode {QDataType val;struct QueueNode* next;
}QNode;
typedef struct Queue {QNode* phead;QNode* ptail;int size;
}Queue;
// 队尾插入
void QueuePush(Queue* pq, QDataType x);
// 队头删除
void QueuePop(Queue* pq);

采取这种方式,队头队尾指针作为Queue结构体变量,改变队头队尾指针只需传递该结构体的一级指针即可。

既避免了使用二级指针可能导致的的接口不一致问题,也使得插入删除方法大的参数减少。

3.3 Queue.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int QDataType;
typedef struct QueueNode {QDataType val;struct QueueNode* next;
}QNode;
typedef struct Queue {QNode* phead;QNode* ptail;int size;
}Queue;
// 初始化
void QueueInit(Queue* pq);
// 销毁
void QueueDestory(Queue* pq);
// 队尾插入
void QueuePush(Queue* pq, QDataType x);
// 队头删除
void QueuePop(Queue* pq);
// 计算列表元素个数;
int QueueSize(Queue* pq);
// 取队头/队尾数据
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);
// 判空
bool QueueEmpty(Queue* pq);

3.4 Queue.c

#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;// 情况1:队列为空if (pq->ptail == NULL) {pq->phead = pq->ptail = newNode;}// 情况2:队列不为空:队尾插入else {pq->ptail->next = newNode;pq->ptail = newNode;}pq->size++;
}
// 队头删除
void QueuePop(Queue* pq) {assert(pq);assert(QueueSize(pq)!=0);// 情况1:队列仅一个结点if (pq->phead->next == NULL) {free(pq->phead);pq->phead = pq->ptail = NULL;}// 情况2:队列有多个结点else {QNode* pheadNext = pq->phead->next;free(pq->phead);pq->phead = NULL;pq->phead = pheadNext;}pq->size--;
}
// 计算列表元素个数;
int QueueSize(Queue* pq) {return pq->size;
}
// 取队头/队尾数据
QDataType QueueFront(Queue* pq) {assert(pq);assert(pq->phead);return pq->phead->val;
}
QDataType QueueBack(Queue* pq) {assert(pq);assert(pq->phead);return pq->ptail->val;
}
// 判空
bool QueueEmpty(Queue* pq) {assert(pq);return pq->size == 0;
}
// 销毁
void QueueDestory(Queue* pq) {assert(pq);QNode* cur = pq->phead;while (cur) {QNode* curNext = cur->next;free(cur);cur = NULL;cur = curNext;}pq->phead = pq->ptail = NULL;
}

3.5 Test_Queue.c

#include"Queue.h"
int main() {Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);while (!QueueEmpty(&q)) {printf("%d ", QueueFront(&q));QueuePop(&q);}QueueDestory(&q);return 0;
}

注:部分方法实现细节

对于队头的删除操作,按照方法完善思路,首先应该是考虑多个结点的无特殊情况,而后考虑对于删除结点的特殊操作进行补充:

(1)需保证队列当中有结点可删,即队列数据个数不为0:可直接使用assert实现;

(2)若队列仅剩一个元素,按当前无特殊情况处理的方法实现,则pq->ptail未置空,使得其成为野指针,故需对其进行单独处理。

综合以上两点,方法实现如下:

// 队头删除
void QueuePop(Queue* pq) {assert(pq);assert(QueueSize(pq)!=0);QNode* pheadNext = pq->phead->next;free(pq->phead);pq->phead = NULL;pq->phead = pheadNext;pq->size--;// 特殊情况单独处理:队列仅有一个结点if (pq->phead == NULL) {pq->ptail = NULL;}
}

这种方法框架可以正确实现功能,但程序结构并不清晰,可以在此基础上进行结构的优化,即使用分支处理① 队列仅有一个结点 ② 队列有≥2个结点。具体实现见3.4部分程序,此处不再重复。

相关文章:

【数据结构】_队列的结构与实现

目录 1. 队列的概念和结构 2. 队列的应用 3. 队列的实现 3.1 队列实现的底层结构选择 3.2 结构体设计 3.2.1 仅为链表结点设计结构体 3.2.2 为链表再设计一个结构体 3.3 Queue.h 3.4 Queue.c 3.5 Test_Queue.c 注&#xff1a;部分方法实现细节 1. 队列的概念和结构 …...

机器学习--2.多元线性回归

多元线性回归 1、基本概念 1.1、连续值 1.2、离散值 1.3、简单线性回归 1.4、最优解 1.5、多元线性回归 2、正规方程 2.1、最小二乘法 2.2、多元一次方程举例 2.3、矩阵转置公式与求导公式 2.4、推导正规方程0的解 2.5、凸函数判定 成年人最大的自律就是&#xff1a…...

MySQL时间类型相关总结(DATETIME, TIMESTAMP, DATE, TIME, YEAR)

MySQL时间类型相关总结(DATETIME, TIMESTAMP, DATE, TIME, YEAR) MySQL官方文档&#xff1a; https://dev.mysql.com/doc/refman/8.0/en/date-and-time-types.html 一. 对比&#xff1a; 在 MySQL 中&#xff0c;处理时间相关的数据类型主要有以下几种&#xff1a;DATE、TIME、…...

朴素贝叶斯原理

在所有的机器学习分类算法中&#xff0c;朴素贝叶斯和其他绝大多数的分类算法都不同。对于大多数的分类算法&#xff0c;比如决策树,KNN,逻辑回归&#xff0c;支持向量机等&#xff0c;他们都是判别方法&#xff0c;也就是直接学习出特征输出Y和特征X之间的关系&#xff0c;要么…...

k8s中,一.pod污点,二.pod容器污点容忍策略,三.pod优先级(PriorityClass类)

一.pod污点:污点是让节点与pod产生排斥的一类规则污点标签的命令1.查看污点标签kubectl describe nodes 节点名2.设置污点标签kubectl taint node 节点名 key值value值:污点标签种类3.删除污点标签kubectl taint node 节点名 key值value值:污点标签种类-4.污点标签种类驱逐:NoE…...

【重生之学习C语言----水仙花篇】

目录 ​编辑 ----------------------------------------begin-------------------------------------- 一、什么是水仙花数&#xff1f; 二、问题分析 确定数字的位数&#xff1a;计算输入数字的位数 n。 分离每一位数字&#xff1a;例如将 153 分离为 1、5、3。 计算各…...

两步构建 AI 总结助手,实现智能文档摘要

在信息极度丰富的当下&#xff0c;如何从海量且复杂的文件资料中筛选出关键内容&#xff0c;成为了不少企业和个人急需解决的问题。本次解决方案将向您介绍&#xff0c;如何通过函数计算 FC 阿里云百炼平台搭建智能 AI 总结助手&#xff0c;实现高效的文本自动总结和信息提取。…...

承压金字塔(蓝桥杯17C)

文件读取&#xff0c;与写入&#xff1a;C 文件和流 | 菜鸟教程 #include <iostream> #include <fstream> #include <string> using namespace std; double sum[30][30]; int main() {ifstream infile("C:\\Users\\xutianci\\OneDrive\\Desktop\\TMOCC\…...

day33-数据同步rsync

一、Rsync本地模式和远程模式 纯通过rsync的命令&#xff0c;来实现&#xff0c;数据目录A 拷贝到数据目录B 也就是模拟cp的用法 很简单 1.安装 yum install rsync -y 2.命令语法&#xff0c;分几个模式 - 本地模式 rsync 参数 源路径 目标路径 rsync -xxxxx /var…...

Android 实现首页Tab切换并且支持懒加载功能详解

目录 1. 添加依赖2. 布局文件3. 创建 Fragment4. 创建适配器5. 在 MainActivity 中设置 TabLayout 和 ViewPager2 1. 添加依赖 在 build.gradle 文件中添加以下依赖&#xff1a; implementation androidx.viewpager2:viewpager2:1.1.0-beta01 implementation com.google.andr…...

[Android] 360行车记录仪谷歌版

[Android] 360行车记录仪谷歌版 链接&#xff1a;https://pan.xunlei.com/s/VOIQYq-jmW8Jpb8y3EIA3YdtA1?pwd3abw# 新买的360行车记录仪&#xff0c;配套软件让安装360智慧生活软件&#xff0c;二百多兆&#xff0c;各种功能齐全、忒齐全&#xff0c;好多用不到&#xff0c;…...

基于Redis分布式锁

1. 获取锁的过程 使用SETNX命令&#xff1a;SETNX&#xff08;SET if Not eXists&#xff09;是一个原子操作&#xff0c;它会在指定的key不存在时&#xff0c;将key的值设置为给定的value&#xff0c;并返回1&#xff1b;如果key已经存在&#xff0c;则不做任何操作&#xff0…...

Spring Boot 条件注解:@ConditionalOnProperty 完全解析

在 Spring Boot 项目中&#xff0c;有时候我们希望根据配置文件中的某个属性值来决定是否启用某个功能或加载某个组件。此时&#xff0c;ConditionalOnProperty 注解就可以发挥作用。它通过配置文件的属性值控制 Bean 或配置类的加载&#xff0c;使得我们的程序更具灵活性。 本…...

canny边缘检测

Canny边缘检测算法是一种广泛使用的边缘检测方法&#xff0c;由John F.Canny在1986年提出。它被认为是边缘检测的“黄金标准”&#xff0c;因为它在检测边缘的同时能够很好地抑制噪声&#xff0c;并且能够精确地定位边缘。Canny算法通过一系列步骤来实现鲁棒的边缘检测&#xf…...

团建 蓝桥杯省a 15

问题描述 小蓝正在和朋友们团建&#xff0c;有一个游戏项目需要两人合作&#xff0c;两个人分别拿到一棵大小为 nn 和 mm 的树&#xff0c;树上的每个结点上有一个正整数权值。 两个人需要从各自树的根结点 1 出发走向某个叶结点&#xff0c;从根到这个叶结点的路径上经过的所…...

【逻辑学导论】1.6 有效性和真实性

当一个演绎论证成功地将结论和前提必然地联系起来&#xff0c;它是有效的。有效性是针对论证的各命题之间的关系而言的。一个论证是有效的&#xff0c;当且仅当它不可能有真前提和假结论&#xff0c;当且仅当其结论是从其前提逻辑必然地推导出来的。因此&#xff0c;有效性永远…...

IDEA 中集成 Maven,配置环境、创建以及导入项目

目录 在 IntelliJ IDEA 中集成 Maven 并配置环境 1. 打开 IDEA 设置 2. 定位 Maven 配置选项 3. 配置 Maven 路径 4. 应用配置 创建 Maven 项目 1. 新建项目 2. 选择项目类型 3. 配置项目信息 4. 确认 Maven 设置 5. 完成项目创建 导入 Maven 项目 1. 打开导入窗口…...

Qt跨屏窗口的一个Bug及解决方案

如果我们希望一个窗口覆盖用户的整个桌面&#xff0c;此时就要考虑用户有多个屏幕的场景&#xff08;此窗口要横跨多个屏幕&#xff09;&#xff0c;由于每个屏幕的分辨率和缩放比例可能是不同的&#xff0c;Qt底层在为此窗口设置缩放比例&#xff08;DevicePixelRatio&#xf…...

Vue WebSocket简单应用 ws

webSocket应用 <template><div></div> </template><script> import { getToken } from "/utils/auth"; export default {data() {return {url: "",Socket: null, //socket对象lockReconnect: false, //锁定拒绝重连close: …...

快速单机部署ollama v0.5.7 +openwebui(免去网络环境干扰)

1 概述 本文介绍在一台机器上快速部署测试ollama和openwebui&#xff0c;免去国内网络环境的干扰。 2 环境 2.1 环境 版本信息如下&#xff1a; a、操作系统&#xff1a;centos 7.9 c、docker版本&#xff1a;20.10.5-3 3 部署 3.1 安装docker yum install -y yum-util…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时&#xff0c;Again增益0db变化为6DB&#xff0c;画面的变化只有2倍DN的增益&#xff0c;比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析&#xff1a; 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

Caliper 配置文件解析:fisco-bcos.json

config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...

CppCon 2015 学习:Time Programming Fundamentals

Civil Time 公历时间 特点&#xff1a; 共 6 个字段&#xff1a; Year&#xff08;年&#xff09;Month&#xff08;月&#xff09;Day&#xff08;日&#xff09;Hour&#xff08;小时&#xff09;Minute&#xff08;分钟&#xff09;Second&#xff08;秒&#xff09; 表示…...

算法—栈系列

一&#xff1a;删除字符串中的所有相邻重复项 class Solution { public:string removeDuplicates(string s) {stack<char> st;for(int i 0; i < s.size(); i){char target s[i];if(!st.empty() && target st.top())st.pop();elsest.push(s[i]);}string ret…...

Mac flutter环境搭建

一、下载flutter sdk 制作 Android 应用 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 1、查看mac电脑处理器选择sdk 2、解压 unzip ~/Downloads/flutter_macos_arm64_3.32.2-stable.zip \ -d ~/development/ 3、添加环境变量 命令行打开配置环境变量文件 ope…...

统计学(第8版)——统计抽样学习笔记(考试用)

一、统计抽样的核心内容与问题 研究内容 从总体中科学抽取样本的方法利用样本数据推断总体特征&#xff08;均值、比率、总量&#xff09;控制抽样误差与非抽样误差 解决的核心问题 在成本约束下&#xff0c;用少量样本准确推断总体特征量化估计结果的可靠性&#xff08;置…...

使用ch340继电器完成随机断电测试

前言 如图所示是市面上常见的OTA压测继电器&#xff0c;通过ch340串口模块完成对继电器的分路控制&#xff0c;这里我编写了一个脚本方便对4路继电器的控制&#xff0c;可以设置开启时间&#xff0c;关闭时间&#xff0c;复位等功能 软件界面 在设备管理器查看串口号后&…...