【夜深人静学数据结构与算法 | 第九篇】栈与队列

news2024/11/18 9:35:48

目录

​前言:

栈:

栈的实际应用: 

队列:

队列的实际应用:

总结:


前言:

        栈与队列是我们学习的两个经典的数据结构,这两个数据结构应用广泛,在计算机内有很多底层应用,而很多算法也是依靠栈和队列来实现的,因此我们要想学好数据结构与算法,就要学好栈与队列这两个最经典的数据机构。

栈:

栈是一种后进先出(Last-In-First-Out,LIFO)的数据结构,它可以实现快速的数据插入和删除操作。

栈可以具备以下几个特点:

1. 栈中添加和删除元素都在同一个位置进行,即栈顶。
2. 栈中元素的添加和删除顺序是相反的,即后进先出。
3. 栈的长度是动态变化的,但它有一个默认或者是最大长度限制。

在栈中,新元素被插入到栈顶位置,称为“压入”(push)操作;而栈顶元素被删除称为“弹出”(pop)操作。栈的本质是一种线性结构,可以使用数组或链表来实现,但由于它的特殊性,通常使用数组来实现更加便捷。

#include <stdio.h>
#include <stdbool.h>

#define MAX_SIZE 10

int top = -1; // 栈顶指针
int arr[MAX_SIZE]; // 存储栈数据的数组

// 添加元素
bool push(int item) {
    if (top >= MAX_SIZE-1) {
        printf("Stack Overflow\n");
        return false;
    } else {
        arr[++top] = item;
        printf("Pushed %d into the stack\n", item);
        return true;
    }
}

// 弹出元素
int pop() {
    if (top < 0) {
        printf("Stack Underflow\n");
        return -1;
    } else {
        int item = arr[top--];
        printf("Popped %d from the stack\n", item);
        return item;
    }
}

// 返回栈顶元素
int peek() {
    if (top < 0) {
        printf("Stack is empty\n");
        return -1;
    } else {
        return arr[top];
    }
}

// 判断栈是否为空
bool isEmpty() {
    return top == -1;
}

// 返回栈中元素个数
int size() {
    return top + 1;
}

栈的实际应用: 

栈是计算机科学中基础的数据结构之一,它在程序设计和开发中有以下几个常见的作用:

1. 算法实现:栈可以被用来实现很多算法,例如:逆波兰表达式求值、中缀表达式转后缀表达式、深度优先遍历等。

2. 函数调用:在函数调用过程中,调用函数时的所有本地变量都会存储在一个函数调用栈中。当函数返回时,局部变量从栈中删除。函数调用栈跟踪函数调用顺序和状态。

3. 内存分配:内存分配函数(如 malloc 和 calloc 等)使用堆栈结构来存储和管理分配的内存块。

4. 缓存和历史记录:在Web开发中,栈可以用来实现浏览器缓存和历史记录,以保存用户的访问记录。

5. 数据结构实现:许多数据结构,如树、图、队列、堆等都可以使用栈来实现。

6. 编译器实现:编译器在编译和解析源码时,需要用到栈来处理语法分析和执行过程。

总言而之,栈是计算机科学中非常重要的数据结构,它帮助程序员解决了各种问题和挑战,不仅可以提高程序的执行效率,而且可以使代码更加简洁,易于理解和维护。

队列:

队列(Queue)是一种先进先出(FIFO)的线性数据结构。它只允许在队列的一端进行插入操作,而在另一端进行删除操作。原则上,第一个被插入的元素必须先被删除,这个规则被称为“先进先出”,简称为 FIFO。

和栈不同的是,队列的两端分别称为队尾和队头,插入操作插入在队尾,删除操作则是删除队头的元素。队列的一个重要特性是它可以帮助我们完成在大量数据集合或多任务下的管理和调度。

队列可以具备以下几个特点:

  1. 先进先出(FIFO):队列的基本操作是在队尾入队和在队头出队。元素是按照它们入队的先后顺序排队等待出队,最先被入队的元素要先被出队。

  2. 只允许在队尾进行插入操作,只允许在队头进行删除操作:插入操作将元素加到队列的尾部,删除操作从队列的头部删除元素。因为队列只允许一侧进一侧出,所以保证了FIFO的顺序。

  3. 队列的长度可以动态变化:队列可以根据需要动态增加或减少,只要内存空间足够。这是与数组的静态大小不同的一个特点。

  4. 队列可以为空:当队列中没有元素时,我们说它是空队列。这是因为队列的长度是动态变化的,因此是有可能为空的。

  5. 队列可以具有大小限制:队列可以被限制成固定大小,当队列容量达到最大值后,继续插入元素就会失败,这是顺序存储队列的一个常见特点。

  6. 队列可以支持并发操作:队列可以被多个线程同时访问,因为队列的各个操作都是原子性的和无状态的。因此,它可以作为一个数据缓冲区在生产者和消费者之间传递数据。

常见的队列有数组队列和链表队列。在数组队列中,元素存储在一个固定大小的数组中。在链表队列中,元素是通过链表链接在一起的。

队列常见的操作有:入队(Enqueue)、出队(Dequeue)、获取队头元素(Front)、获取队尾元素(Rear)、判空(IsEmpty)、判满(IsFull)等。

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

#define MAX_SIZE 100

typedef struct {
    int items[MAX_SIZE];
    int front;
    int rear;
} Queue;

void initializeQueue(Queue *q) {
    q->front = -1;
    q->rear = -1;
}

bool isFull(Queue *q) {
    return (q->rear == MAX_SIZE - 1);
}

bool isEmpty(Queue *q) {
    return (q->front == -1 && q->rear == -1);
}

void enqueue(Queue *q, int value) {
    if (isFull(q)) {
        printf("Queue is full.\n");
    }
    else if (isEmpty(q)) {
        q->front = 0;
        q->rear = 0;
        q->items[q->rear] = value;
    }
    else {
        q->rear++;
        q->items[q->rear] = value;
    }
}

int dequeue(Queue *q) {
    int item;
    if (isEmpty(q)) {
        printf("Queue is empty.\n");
        item = -1;
    }
    else if (q->front == q->rear) {
        item = q->items[q->front];
        q->front = -1;
        q->rear = -1;
    }
    else {
        item = q->items[q->front];
        q->front++;
    }
    return item;
}

int main() {
    Queue q;
    initializeQueue(&q);

    enqueue(&q, 10);
    enqueue(&q, 20);
    enqueue(&q, 30);
    enqueue(&q, 40);

    printf("Dequeued item: %d\n", dequeue(&q));
    printf("Dequeued item: %d\n", dequeue(&q));

    return 0;
}

队列的实际应用:

1. 缓存:电脑和移动设备中,缓存是数据进行存储和访问的一种方式。队列在缓存中起到了很重要的作用,数据先进入队列,然后先出队列,这样保证了缓存的数据按照先后顺序进行读写,提高了缓存的读写效率。

2. 生产者-消费者问题:队列可以被用于生产者和消费者之间通信和传递数据,生产者将数据放入队列尾端,消费者从队列开头取出数据并进行处理,以此实现两者之间的同步和协调。

3. 线程池: 队列可以被用于控制线程,线程池将任务放到队列尾部,并由正在等待的线程去处理队列中的任务,这样就可以以有限的线程数量来处理大量的任务。

4. 消息队列:消息队列用于异步通讯或不同进程/线程之间的信息传递,例如:消息队列中的电子邮件平台或聊天程序。消息被添加到队列尾部,然后按照先后顺序排队等待被处理。

5. 订单排队:一些商店中可以在队列中等待客户完成支付、取货等操作。可以使用队列来控制顾客的前后顺序,确保公平性。

6. 睡眠唤醒队列:操作系统中,进程在等待操作系统资源时可以被放到一个睡眠队列中,并被挂起等待资源被释放,唤醒时再加入到就绪队列中运行。

总之,队列是很重要的数据结构之一,它被广泛地应用于各种系统和场合中,从操作系统、数据结构到应用程序等各个领域。它简洁易懂,具有良好的扩展性和应用力,是我们在解决各种实际问题中必不可少的工具之一。

总结:

        栈与队列是两个很经典的数据结构,因此我们要学好这两个数据结构,才可以对更多基于这两个数据结构所构成的算法有更加深刻的印象。

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

 

 

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

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

相关文章

操作系统2——进程的描述与控制

本系列博客重点在深圳大学操作系统课程的核心内容梳理&#xff0c;参考书目《计算机操作系统》&#xff08;有问题欢迎在评论区讨论指出&#xff0c;或直接私信联系我&#xff09;。 梗概 本篇博客主要介绍操作系统第二章进程的描述与控制的相关知识。 目录 一、前驱图与程序…

大数据从0到1的完美落地之Flume案例1

案例演示 案例演示&#xff1a;AvroMemoryLogger Avro Source&#xff1a;监听一个指定的Avro端口&#xff0c;通过Avro端口可以获取到Avro client发送过来的文件&#xff0c;即只要应用程序通过Avro端口发送文件&#xff0c;source组件就可以获取到该文件中的内容,输出位置为…

数据库详细讲解--下

数据库详细讲解–下 mysql 表外连接 外连接 1.左外连接&#xff08;如果左侧的表完全显示我们就说是左外连接&#xff09; 2.右外连接&#xff08;如果右侧的表完全显示我们就说是右外连接&#xff09; 3.使用左连接&#xff08;显示所有人的成绩&#xff0c;如果没有成绩…

4自由度并联机器狗实现行走功能

1. 功能说明 本文示例将实现R328a样机4自由度并联机器狗行走的功能。 2. 电子硬件 在这个示例中&#xff0c;我们采用了以下硬件&#xff0c;请大家参考&#xff1a; 主控板 Basra主控板&#xff08;兼容Arduino Uno&#xff09;‍ 扩展板 Bigfish2.1扩展板‍ 电池7.4V锂电池 …

【Linux】进程优先级 进程切换 环境变量

目录 一、进程优先级 1、优先级概念 2、优先级特点 3、修改Linux下的优先级 二、进程切换 1、进程特性 2、进程切换 三、环境变量 1、基本概念 2、常见环境变量 3、查看环境变量方法 4、PATH环境变量 5、和环境变量相关的命令 6、环境变量的组织方式 7、通过代码如何获取环境…

io.netty学习(十一)Reactor 模型

目录 前言 传统服务的设计模型 NIO 分发模型 Reactor 模型 1、Reactor 处理请求的流程 2、Reactor 三种角色 单Reactor 单线程模型 1、消息处理流程 2、缺点 单Reactor 多线程模型 1、消息处理流程 2、缺点 主从Reactor 多线程模型 主从Reactor 多线程模型示例 1…

索尼笔记本U盘重装Win10系统教程图解

很多使用索尼笔记本的用户想要给笔记本重装一下Win10系统&#xff0c;但不清楚具体要怎么操作&#xff0c;首先用户需要确保自己的索尼笔记本电脑能够正常联网&#xff0c;还需要准备一个8G以上的U盘&#xff0c;接着按照小编分享的索尼笔记本U盘重装Win10系统教程图解操作&…

怎么高效的通过爬虫获取数据

导语&#xff1a;在当今数字化时代中&#xff0c;获取数据已成为许多企业和个人的重要需求。在快速获取数据时&#xff0c;通过爬虫技术迅速获取网络数据已成为一项重要的技能和技术。然而&#xff0c;在应用爬虫技术前&#xff0c;需要注意一些重要的问题。本文总结了从数据来…

九大数据结构

数据结构想必大家都不会陌生&#xff0c;对于一个成熟的程序员而言&#xff0c;熟悉和掌握数据结构和算法也是基本功之一。数据结构本身其实不过是数据按照特点关系进行存储或者组织的集合&#xff0c;特殊的结构在不同的应用场景中往往会带来不一样的处理效率。 常用的数据结…

IDEA上面书写wordcount的Scala文件具体操作

系列文章目录 IDEA创建项目的操作步骤以及在虚拟机里面创建Scala的项目简单介绍_intellij 创建scala 目录 系列文章目录 1、编写Scala程序 2、更换pom.xml文件 3、更新Maven的依赖文件 4、执行代码即可 总结 前言 本文主要在上述文章的基础上编辑和创建一个WordCount应…

Linux常用命令——ftp命令

在线Linux命令查询工具 ftp 用来设置文件系统相关功能 补充说明 ftp命令用来设置文件系统相关功能。ftp服务器在网上较为常见&#xff0c;Linux ftp命令的功能是用命令的方式来控制在本地机和远程机之间传送文件&#xff0c;这里详细介绍Linux ftp命令的一些经常使用的命令…

【23-06-25:window基础命令学习】

目录 命令提示符cd /? 查看cd 语法 切换文件目录cd /d d:\ 改变当前的驱动器到D盘&#xff0c; 根目录切换到D盘&#xff0c;因为改变了驱动器&#xff0c;所以需要加上 /dDIRmd 命令 创建目录&#xff08;文件夹&#xff09; &#xff0c;也可以直接创建多级子目录![在这里插…

MySql进阶篇(1)

MySql进阶篇 一、存储引擎1.1 MySql体系结构1.2 存储引擎的简介1.3 存储引擎的特点1.3.1 innoDB1.3.2 MyISAM1.3.3 Memory1.3.4 上述总结 1.4 存储引擎的选择 二、索引2.1 索引的概述2.2 索引结构2.2.1 二叉树和红黑树2.2.2 B-Tree&#xff08;多路平衡查找树&#xff09;2.2.3…

基于Java+Swing实现天气预报系统

基于JavaSwing实现天气预报系统 一、系统介绍二、功能展示1.主面2.IP定位城市3.通过城市名称查询天气状态4、查看各城区的天气 三、代码展示四、其他系统五、获取源码 一、系统介绍 系统主要通过输入城市名字&#xff08;可通过电脑IP查询所属城市&#xff0c;查询所属城市IP接…

Linux系统编程(exec函数家族和system函数)

文章目录 前言一、exec函数家族二、system函数介绍三、system函数使用总结 前言 本篇文章我们继续讲解多进程编程中的&#xff0c;exec函数家族和system函数。 一、exec函数家族 exec 函数家族是一组在类Unix操作系统中常用的函数&#xff0c;用于在当前进程中执行一个新的程…

STM32模拟I2C协议获取HDC1080温度和湿度传感器数据

STM32模拟I2C协议获取HDC1080温度和湿度传感器数据 HDC1080是一款温湿度传感器&#xff0c;具有如下特点&#xff1a; 其中温度和湿度经过出厂校准。这里介绍STM32模拟I2C总线协议访问HDC1080的HAL库实现范例。 HDC1080电路连接 HDC1080的内部原理及电路连接如下&#xff1…

GIS 功能模块设计

文章目录 1 .地图渲染2. 地图控制设备管理模块设计1 . 导航树管理2. 查询定位功能3. 资源管理功能4 . 入沟管理管线业务功能模块设计1 .轨迹图管理2. 单线图管理3. 设备接线图管理4. 工井立视图管理其他管理模块1 .用户管理功能2. 数据导入功能 1 .地图渲染 主要解决将指定的空…

16个小的UI设计规则却能产生巨大的影响

微信搜索 【大迁世界】, 我会第一时间和你分享前端行业趋势&#xff0c;学习途径等等。 本文 GitHub https://github.com/qq449245884/xiaozhi 已收录&#xff0c;有一线大厂面试完整考点、资料以及我的系列文章。 快来免费体验ChatGpt plus版本的&#xff0c;我们出的钱 体验地…

最新导则下生态环评报告编制技术(报告篇、制图篇、指数篇、综合应用)

根据生态环评内容庞杂、综合性强的特点&#xff0c;依据生态环评最新导则&#xff0c;将内容分为4大篇章(报告篇、制图篇、指数篇、综合篇)、10大专题(生态环评报告编制、土地利用图的制作、植被类型及植被覆盖度图的制作、物种适宜生境分布图的制作、生物多样性测定、生物量及…

VUE L 条件列表渲染 ⑧

目录 文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持✨ V u e j s Vuejs Vuejs条件渲染列表渲染 基本列表 Key的原理 列表过滤 列表排序 列表更新小问题 监测数据改变的原理~对象 V u e S e t VueSet VueSet的…