【数据结构】线性表(十一)队列:双端队列及其基本操作(初始化、判空、判满、头部入队、尾部入队、头部出队、尾部出队、存取队首队尾元素)

news2024/10/7 14:24:23

文章目录

  • 一、队列
    • 1. 定义
    • 2. 基本操作
  • 二、顺序队列
  • 三、链式队列
  • 双端队列
    • 0. 头文件
    • 1. 队列结构体
    • 2. 初始化
    • 3. 判断队列是否为空
    • 4. 判断队列是否已满
    • 5. 头部入队
    • 6. 尾部入队
    • 7. 头部出队
    • 8. 尾部出队
    • 9. 存取队列头部的元素
    • 10. 存取队列尾部的元素
    • 11. 释放队列内存
    • 12. 主函数
    • 13. 代码整合

一、队列

1. 定义

  队列是一种操作受限的线性表,对于它的所有插入都在表的一端进行,所有的删除(以至几乎所有的存取)都在表的另一端进行,且这些操作又都是按照先进先出(FIFO)的原则进行的。进行删除的一端称为队头(front),进行插入的一端称为队尾(rear)。没有元素的队列称为空队列(简称空队)。

在这里插入图片描述
  队列就像生活中排队购物,新来的人只能加入队尾(假设不允许插队),购物结束后先离开的总是队头(假设无人中途离队)。也就是说,先加入队列的成员总是先离开队列,因此队列被称为先进先出(First In First Out)的线性表,简称为FIFO表。如图,在空队列中依次加入元素a1,a2,a3,a4,a5,出队次序仍然是a1,a2,a3,a4,a5 .

2. 基本操作

  • 队列是受限的线性表,其基本操作包括

    • IsEmpty() : 判断队列是否为空;
    • isFull():判断队列是否为满;
    • enqueue() :向队尾添加元素(入队);
    • dequeue() :删除队首元素(出队);
    • peek():获取队首的元素值(存取);
  • 同普通线性表一样,队列也可以用顺序存储和链接存储两种方式来实现:

二、顺序队列

  参考前文:【数据结构】线性表(八)队列:顺序队列及其基本操作(初始化、判空、判满、入队、出队、存取队首元素)

三、链式队列

  参考前文:【数据结构】线性表(九)队列:链式队列及其基本操作(初始化、判空、入队、出队、存取队首元素)

双端队列

  双端队列(Double-ended Queue,简称Deque)可以在队列的头部和尾部进行元素的插入和删除操作,因此可以看作是一种特殊的队列和栈的结合。

双端队列的操作包括:

  • 在队列头部插入元素(头部入队);
  • 在队列尾部插入元素(尾部入队);
  • 在队列头部删除元素(头部出队),并返回该元素;
  • 在队列尾部删除元素(尾部出队),并返回该元素;
  • 获取队列头部的元素,但不删除它;
  • 获取队列尾部的元素,但不删除它;
  • 判断队列是否为空。

  双端队列可以用于解决一些特定的问题,例如实现滑动窗口最大值、字符串处理等。它的灵活性使得在某些场景下比普通队列更加方便和高效。
图片来源于网络,侵删

0. 头文件

#include <stdio.h>
#include <stdlib.h>
  • 两个头文件
    • stdio.h用于输入输出操作
    • stdlib.h用于内存分配和释放

1. 队列结构体

typedef struct {
    int* elements;  // 存储队列元素的数组
    int front;      // 队列头部索引
    int rear;       // 队列尾部索引
    int size;       // 队列的最大容量
} Deque;

2. 初始化

void initDeque(Deque* deque, int capacity) {
    deque->elements = (int*)malloc(capacity * sizeof(int));
    deque->front = -1;
    deque->rear = -1;
    deque->size = capacity;
}
  • 使用动态内存分配函数 malloc 分配了一个大小为 capacity * sizeof(int) 的整型数组,并将其地址赋值给 deque->elements
  • deque->frontdeque->rear 初始化为 -1,表示队列为空。
  • deque->size 设置为传入的容量值。

3. 判断队列是否为空

int isEmpty(Deque* deque) {
    return deque->front == -1;
}

  通过检查队列的头部索引是否为-1来判断队列是否为空。

4. 判断队列是否已满

int isFull(Deque* deque) {
    return deque->rear == deque->size - 1;
}

  通过检查队列的尾部索引是否等于队列的最大容量减1来判断队列是否已满。

5. 头部入队

void insertFront(Deque* deque, int element) {
    if (isEmpty(deque)) {
        deque->front = 0;
        deque->rear = 0;
    } else if (deque->front == 0) {
        deque->front = deque->size - 1;
    } else {
        deque->front--;
    }
    deque->elements[deque->front] = element;
}
  • 如果队列为空(即 isEmpty(deque) 返回真),则将队列头部和尾部索引都设置为 0。
  • 否则,如果队列头部索引为 0,则将其设置为队列的最大容量减 1,否则将其递减 1。
  • 将元素 element 存储到队列头部索引对应的位置。

6. 尾部入队

void insertRear(Deque* deque, int element) {
    if (isEmpty(deque)) {
        deque->front = 0;
        deque->rear = 0;
    } else if (deque->rear == deque->size - 1) {
        deque->rear = 0;
    } else {
        deque->rear++;
    }
    deque->elements[deque->rear] = element;
}
  • 如果队列为空(即 isEmpty(deque) 返回真),则将队列头部和尾部索引都设置为 0。
  • 否则,如果队列尾部索引等于队列的最大容量减 1,则将其设置为 0,否则将其递增 1。
  • 将元素 element 存储到队列尾部索引对应的位置。

7. 头部出队

void deleteFront(Deque* deque) {
    if (isEmpty(deque)) {
        return;
    }
    if (deque->front == deque->rear) {
        deque->front = -1;
        deque->rear = -1;
    } else if (deque->front == deque->size - 1) {
        deque->front = 0;
    } else {
        deque->front++;
    }
}
  • 如果队列为空(即 isEmpty(deque) 返回真),则直接返回,不进行任何操作。
  • 否则,如果队列头部索引等于队列尾部索引,表示队列中只有一个元素,将队列头部和尾部索引都设置为 -1。
  • 否则,如果队列头部索引等于队列的最大容量减 1,则将其设置为 0,否则将其递增 1。

8. 尾部出队

void deleteRear(Deque* deque) {
    if (isEmpty(deque)) {
        return;
    }
    if (deque->front == deque->rear) {
        deque->front = -1;
        deque->rear = -1;
    } else if (deque->rear == 0) {
        deque->rear = deque->size - 1;
    } else {
        deque->rear--;
    }
}
  • 如果队列为空(即 isEmpty(deque) 返回真),则直接返回,不进行任何操作。
  • 否则,如果队列尾部索引等于队列头部索引,表示队列中只有一个元素,将队列头部和尾部索引都设置为 -1。
  • 否则,如果队列尾部索引等于 0,则将其设置为队列的最大容量减 1,否则将其递减 1。

9. 存取队列头部的元素

int getFront(Deque* deque) {
    if (isEmpty(deque)) {
        return -1;  // 队列为空时返回一个特定的值,可以根据实际情况进行修改
    }
    return deque->elements[deque->front];
}
  • 如果队列为空(即 isEmpty(deque) 返回真),则返回一个特定的值(这里是 -1),表示队列为空。
  • 否则,返回队列头部索引对应的元素。

10. 存取队列尾部的元素

int getRear(Deque* deque) {
    if (isEmpty(deque)) {
        return -1;  // 队列为空时返回一个特定的值,可以根据实际情况进行修改
    }
    return deque->elements[deque->rear];
}
  • 如果队列为空(即 isEmpty(deque) 返回真),则返回一个特定的值(这里是 -1),表示队列为空。
  • 否则,返回队列尾部索引对应的元素。

11. 释放队列内存

void freeDeque(Deque* deque) {
    free(deque->elements);
}

  使用 free 函数释放 deque->elements 指向的动态内存。

12. 主函数

int main() {
    Deque deque;
    int capacity = 5;  // 设置队列的容量

    // 初始化双端队列
    initDeque(&deque, capacity);

    // 在队列头部插入元素
    insertFront(&deque, 1);
    insertFront(&deque, 2);

    // 在队列尾部插入元素
    insertRear(&deque, 3);
    insertRear(&deque, 4);

    // 获取队列头部和尾部的元素
    printf("Front: %d\n", getFront(&deque));
    printf("Rear: %d\n", getRear(&deque));

    // 在队列头部删除元素
    deleteFront(&deque);

    // 在队列尾部删除元素
    deleteRear(&deque);

    // 获取更新后的队列头部和尾部的元素
    printf("Front: %d\n", getFront(&deque));
    printf("Rear: %d\n", getRear(&deque));

    // 释放队列内存
    freeDeque(&deque);

    return 0;
}

在这里插入图片描述

13. 代码整合

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int* elements;  // 存储队列元素的数组
    int front;      // 队列头部索引
    int rear;       // 队列尾部索引
    int size;       // 队列的最大容量
} Deque;

void initDeque(Deque* deque, int capacity) {
    deque->elements = (int*)malloc(capacity * sizeof(int));
    deque->front = -1;
    deque->rear = -1;
    deque->size = capacity;
}

int isEmpty(Deque* deque) {
    return deque->front == -1;
}

int isFull(Deque* deque) {
    return deque->rear == deque->size - 1;
}

void insertFront(Deque* deque, int element) {
    if (isEmpty(deque)) {
        deque->front = 0;
        deque->rear = 0;
    } else if (deque->front == 0) {
        deque->front = deque->size - 1;
    } else {
        deque->front--;
    }
    deque->elements[deque->front] = element;
}

void insertRear(Deque* deque, int element) {
    if (isEmpty(deque)) {
        deque->front = 0;
        deque->rear = 0;
    } else if (deque->rear == deque->size - 1) {
        deque->rear = 0;
    } else {
        deque->rear++;
    }
    deque->elements[deque->rear] = element;
}

void deleteFront(Deque* deque) {
    if (isEmpty(deque)) {
        return;
    }
    if (deque->front == deque->rear) {
        deque->front = -1;
        deque->rear = -1;
    } else if (deque->front == deque->size - 1) {
        deque->front = 0;
    } else {
        deque->front++;
    }
}

void deleteRear(Deque* deque) {
    if (isEmpty(deque)) {
        return;
    }
    if (deque->front == deque->rear) {
        deque->front = -1;
        deque->rear = -1;
    } else if (deque->rear == 0) {
        deque->rear = deque->size - 1;
    } else {
        deque->rear--;
    }
}

int getFront(Deque* deque) {
    if (isEmpty(deque)) {
        return -1;  // 队列为空时返回一个特定的值,可以根据实际情况进行修改
    }
    return deque->elements[deque->front];
}

int getRear(Deque* deque) {
    if (isEmpty(deque)) {
        return -1;  // 队列为空时返回一个特定的值,可以根据实际情况进行修改
    }
    return deque->elements[deque->rear];
}

void freeDeque(Deque* deque) {
    free(deque->elements);
}

int main() {
    Deque deque;
    int capacity = 5;  // 设置队列的容量

    // 初始化双端队列
    initDeque(&deque, capacity);

    // 在队列头部插入元素
    insertFront(&deque, 1);
    insertFront(&deque, 2);

    // 在队列尾部插入元素
    insertRear(&deque, 3);
    insertRear(&deque, 4);

    // 获取队列头部和尾部的元素
    printf("Front: %d\n", getFront(&deque));
    printf("Rear: %d\n", getRear(&deque));

    // 在队列头部删除元素
    deleteFront(&deque);

    // 在队列尾部删除元素
    deleteRear(&deque);

    // 获取更新后的队列头部和尾部的元素
    printf("Front: %d\n", getFront(&deque));
    printf("Rear: %d\n", getRear(&deque));

    // 释放队列内存
    freeDeque(&deque);

    return 0;
}

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

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

相关文章

每日一题 2678. 老人的数目(简单)

简单题&#xff0c;不多说 class Solution:def countSeniors(self, details: List[str]) -> int:ans 0for l in details:if int(l[11:13]) > 60:ans 1return ans

CSS设置超出范围滚动条和滚动条样式

CSS设置超出范围滚动条和滚动条样式 效果展示 当块级内容区域超出块级元素范围的时候&#xff0c;就会以滚动条的形式展示&#xff0c;你可以滚动里面的内容&#xff0c;里面的内容不会超出块级区域范围。 未设置超出隐藏&#xff0c;显示滚动条 超出隐藏&#xff0c;显示滚动…

APP软件外包开发设计原则

设计一个成功的APP需要遵循一些关键的设计原则&#xff0c;以确保用户体验良好、功能明晰、吸引力和易用性。以下是一些重要的APP设计原则&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 用户为中心&…

Ubuntu系统中安装libcurl库用来做爬虫

在Ubuntu系统上运行爬虫&#xff0c;可以使用libcurl的方式简单部署libcurl爬虫管理平台。在libcurl库中&#xff0c;可以使用普通任务和定时任务来运行爬虫。同时&#xff0c;还可以添加依赖包和配置消息通知钉钉机器人等功能。如果需要使用Python-bs4库&#xff0c;可以通过系…

从GitHub火到头条!这份万众期待的阿里内部JAVA面试手册,开源了

前言&#xff1a; 现在的互联网开发岗招聘&#xff0c;程序员面试背八股文已经成为了不可逆转的形式&#xff0c;其中一个Java岗几百人在投简历也已经成为了常态&#xff01;更何况一份面试题动辄七八百道&#xff0c;你吃透了&#xff0c;技术只要不是很差&#xff0c;面试怎…

开发中常用的版本管理工具有哪些?

一、是什么 版本控制&#xff08;Version control&#xff09;&#xff0c;是维护工程蓝图的标准作法&#xff0c;能追踪工程蓝图从诞生一直到定案的过程。此外&#xff0c;版本控制也是一种软件工程技巧&#xff0c;借此能在软件开发的过程中&#xff0c;确保由不同人所编辑的…

网站页脚展示备案号并在新标签页中打开超链接

备案时&#xff0c;我们就注意到&#xff0c;备案成功后需要在网站首页底部展示“备案号”&#xff0c;并将备案号链接至https://beian.miit.gov.cn。 这里我使用了WrodPress中的主题&#xff0c;主题自定义中有提供对页脚文本的编辑&#xff0c;支持用css标签定义样式。若是自…

创意无限,图文生成如虎添翼:星火大模型的威力

在数字化的时代&#xff0c;讯飞&#xff08;iFlyTek&#xff09;的星火大模型已经走在了创新的前沿。它以卓越的技术和无与伦比的免费政策&#xff0c;为创作者、开发者和企业家们提供了创新无限的可能性。 星火大模型最新亮点 多样性无限&#xff0c;星火助手数量达4000 星火…

Post-Process1-水下

一、新建第三人称游戏项目&#xff0c;我这里选择C&#xff0c;你也可以选择Blueprint。 新建一个Level&#xff0c;命名为DemoUnderWater 保存一下&#xff0c;命名为DownUnderWater 添加水插件 选择Yes 勾选Show Engine Content和Show Plugin Content&#xff0c;在左侧可以看…

Mysql如何确定执行计划是最优开销?Mysql优化器!

1. 什么是 MySQL 优化器&#xff1f; MySQL 优化器是 MySQL 中的一个核心组件。MySQL 优化器的主要职责在于确定查询的执行计划。在数据库中&#xff0c;同样的查询可以有多种不同的执行方式&#xff0c;如使用不同的索引&#xff0c;使用不同的连接顺序等。每种执行方式都有其…

C++之std::string

string类与头文件包含&#xff1a;#include <string> string构造方法&#xff1a; // string constructor #include <iostream> #include <string>int main () {std::string s0 ("Initial string"); //根据已有字符串构造新的string实例// cons…

紫光展锐发布全新6G白皮书,展望泛在融合发展蓝图

自2019年5G蜂窝技术正式商用以来&#xff0c;5G网络建设如火如荼&#xff0c;各类形态的5G终端层出不穷。5G商用推进的同时&#xff0c;6G研究也在全球范围内拉开帷幕。2023年6月ITU发布了《IMT面向2030及未来发展的框架和总体目标建议书》&#xff08;下文简称“建议书”&…

Java基于SSM开发的企业员工管理系统源码

主要功能 包括部门、岗位、工资、员工、请假、审批管理。普通员工可请假查看工资等&#xff0c;管理员可审批、管理员工工资等。 演示视频&#xff1a; https://www.bilibili.com/video/BV1c94y1j7QM/?share_sourcecopy_web&vd_source11344bb73ef9b33550b8202d07ae139b …

MAC上,自动操作+一行命令,实现图像化的微信双开

通过Mac上的“自动操作”和一行代码实现图像化的Mac双开 1、先看看效果在这里插入图片描述 2、Mac上&#xff0c;一行命令解决微信双开的问题 nohup /Applications/WeChat.app/Contents/MacOS/WeChat > /dev/null 2>&1但是每次通过命令行去操作也太过麻烦&#xff0…

简单易用的操作界面,让你轻松制作电子期刊

随着互联网的发展&#xff0c;电子期刊已经成为了越来越多人的选择。FLBOOK在线制作电子杂志平台作为一款简单易用的操作界面&#xff0c;为用户提供了制作电子期刊的便利。 但是你知道如何使用FLBOOK在线制作电子杂志平台制作一本电子期刊吗&#xff1f; 1.点击开始创作&#…

在配置文件“tsconfig.json”中找不到任何输入。指定的 “include“ 路径为“[“**/*“]”,“exclude“ 路径为[]

在vscode中项目下的tsconfig.json莫名报错 解决办法 在目录中随便创建一个后缀为.ts的文件 便不再报错

人手一个助理,三句话让AI替我们上班

目录 前言 从大模型上长出来的 AI 原生应用&#xff0c;才是关键 而这看起来只是一个小小的办公沟通场景&#xff0c;却是大模型重构的一个非常典型的场景。背后考验的也是大模型的综合能力应用 这种从AI原生角度进行的重构&#xff0c;离不开大模型的理解、生成、逻辑、记…

什么是美颜SDK?深入了解直播实时美颜SDK

美颜已经成为了现代社交媒体和直播应用中的重要元素&#xff0c;它使用户能够在拍摄自拍照片或进行直播时改善其外貌特征。美颜技术的普及离不开美颜SDK&#xff08;软件开发工具包&#xff09;&#xff0c;特别是在直播应用中&#xff0c;直播实时美颜SDK正变得越来越流行。在…

如何解决git 发生冲突的场景?

一、是什么 一般情况下&#xff0c;出现分支的场景有如下&#xff1a; 多个分支代码合并到一个分支时多个分支向同一个远端分支推送 具体情况就是&#xff0c;多个分支修改了同一个文件&#xff08;任何地方&#xff09;或者多个分支修改了同一个文件的名称 如果两个分支中…

景联文科技:针对敏感数据的安全转录服务,护航信息安全

针对数据的安全转录服务&#xff0c;主要是为了确保数据在转录过程中的安全性和隐私保护。这些服务通常会采用一系列严格的安全措施&#xff0c;如数据加密、访问控制、数据脱敏等&#xff0c;以确保敏感数据不会被泄露或滥用。 景联文科技提供特定的数据转录服务&#xff0c;以…