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

这篇具有很好参考价值的文章主要介绍了【夜深人静学数据结构与算法 | 第九篇】栈与队列。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

目录

​前言:

栈:

栈的实际应用: 

队列:

队列的实际应用:

总结:


前言:

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

栈:

栈是一种后进先出(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. 睡眠唤醒队列:操作系统中,进程在等待操作系统资源时可以被放到一个睡眠队列中,并被挂起等待资源被释放,唤醒时再加入到就绪队列中运行。

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

总结:

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

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

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

 文章来源地址https://www.toymoban.com/news/detail-610244.html

 

到了这里,关于【夜深人静学数据结构与算法 | 第九篇】栈与队列的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【夜深人静学数据结构与算法 | 第三篇】 二叉树

    目录  前言:  二叉树: 二叉树的种类:  二叉树的存储方式: 1. 链式存储 2. 数组存储 二叉树的遍历方式 深度优先遍历 广度优先遍历 总结: 本文将会详细的介绍各种常见的树以及相对应的概念,存储方式,遍历方式。树是经典的数据结构,因此我们虽然不能做到手撕各

    2024年02月11日
    浏览(37)
  • 【夜深人静学数据结构与算法 | 第十篇】动态规划

    目录 前言: 动态规划: 常见应用: 解题步骤:  动态规划的简化步骤: 案例: 509. 斐波那契数 - 力扣(LeetCode) 70. 爬楼梯 - 力扣(LeetCode) 62. 不同路径 - 力扣(LeetCode) 总结:         本文我们将为大家讲解一下动态规划的理论知识,并且会讲解几道力扣的经典例题。

    2024年02月11日
    浏览(47)
  • 【夜深人静学习数据结构与算法 | 第十二篇】动态规划——背包问题

      目录  前言:  01背包问题: 二维数组思路: 一维数组思路: 总结:       在前面我们学习动态规划理论知识的时候,我就讲过要介绍一下背包问题,那么今天我们就来讲解一下背包问题。 在这里我们只介绍 01背包 ,至于分组背包和混合背包这种的已经属于竞赛级别的

    2024年02月12日
    浏览(37)
  • 【夜深人静学数据结构与算法 | 第四篇】手撕二叉树遍历

    目录 前言: 二叉树遍历方式: 手撕前中后序遍历(递归)的三大准备 深度优先搜索:  手撕前中后遍历(递归): 手撕前中后序遍历(迭代): 深度优先搜索: 总结:         今天我们将带领大家手撕二叉树的遍历,本篇会分别讲解深度优先搜索法和广度优先有搜索法下

    2024年02月09日
    浏览(34)
  • 【夜深人静学数据结构与算法 | 第二篇】后缀(逆波兰)表达式

    目录 前言:  中缀表达式:  后缀表达式: 中缀表达式转后缀表达式: 后缀表达式计算结果: 总结:  计算机在计算四则运算的时候,由于括号以及运算优先级的存在,并不能够很好的处理所有的运算,为了处理这种情况,我们引入了后缀表达式来优化算法。         

    2024年02月13日
    浏览(40)
  • 【夜深人静学数据结构与算法 | 第七篇】时间复杂度与空间复杂度

    前言:  引入:  时间复杂度:  案例: 空间复杂度: 案例: TIPS:        总结:         今天我们将来介绍时间复杂度和空间复杂度,我们代码的优劣就是依靠这个在评判,以此为背景,我们诞生出了不少的经典思路:用时间换空间,用空间换取时间。而大多数同学

    2024年02月10日
    浏览(52)
  • 夜深人静学32系列10——GPIO中断/NVIC/EXTI/SYSCFG详解,外部中断控制LED

    上期我们学习了GPIO驱动数码管/蜂鸣器/LED和按键等外设,本期我们一起来学习STM32中断的相关内容 当CPU正在处理某个事件的时候,外界发生了紧急事件请求,CPU需要暂停当前的工作,转而去处理这个紧急事件,处理完之后,再次回到之前被中断的地方,继续执行原来的工作,

    2024年01月16日
    浏览(34)
  • 【数据结构入门精讲 | 第九篇】考研408排序算法专项练习(一)

    前面几篇文章介绍的是排序算法,现在让我们开始排序算法的专项练习。 1.希尔排序是稳定的算法。(错) 解析:稳定性是指如果两个元素在排序前后的相对顺序保持不变,那么这个排序算法就是稳定的。对于具有相同的元素,排序后它们的相对位置应该保持不变。

    2024年02月03日
    浏览(36)
  • 软考A计划-真题-分类精讲汇总-第九章(数据结构与算法基础)

    点击跳转专栏=Unity3D特效百例 点击跳转专栏=案例项目实战源码 点击跳转专栏=游戏脚本-辅助自动化 点击跳转专栏=Android控件全解手册 点击跳转专栏=Scratch编程案例 专注于 Android/Unity 和各种游戏开发技巧,以及 各种资源分享 (网站、工具、素材、源码、游戏等) 有什么需要

    2024年02月05日
    浏览(51)
  • 数据结构第九章

    (1)顺序表的查找          1)顺序表查找的结构 顺序查找的过程:从表中最后一个记录开始,逐个进行记录的和给定值的比较。(也就是说,在查找到时候从最后一个元素开始查找,在这个表中位置为0的位置空着,留给你要查找的元素) 在顺序表的查找中,需要

    2024年01月21日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包