【数据结构】栈和队列的应用——括号匹配 + 表达式求值 + 表达式转换 +栈的递归应用+队列在计算机系统中的应用

文章目录

    • 3.栈的应用
      • 3.1 括号匹配问题
      • 3.2 表达式求值
        • 3.2.1 三种算术表达式
        • 3.2.2 后缀表达式
          • A.中缀转后缀
          • B.后缀表达式的计算
        • 3.2.3 前缀表达式
          • A.中缀转前缀
          • B.前缀表达式的计算
        • 3.2.4 中缀表达式的求值
      • 3.3 递归中栈的应用
    • 4.队列的应用

栈基础知识:【数据结构】栈 顺序栈 链栈(共享栈 创建 进栈 出栈 读取)完整代码+解析
队列基础知识:【数据结构】队列 循环队列 双端队列——顺序队列+链式队列完整代码

3.栈的应用

3.1 括号匹配问题

  • 问题阐述

    判断一组有()[]{}这些括号的字符串,判断左右括号是否匹配。

    • 括号需要从里向外一层层匹配,符合栈后进先出的特点,所以用栈解决括号匹配问题。
  • 匹配流程:

  • 算法流程:

    1.创建空栈,顺序遍历括号;

    2.若是左括号,压入栈中,继续扫描;

    3.若是右括号,弹出栈顶元素,判断两个括号类型是否匹配;

    4.遍历完后判断栈是否空。

#include<stdio.h>
#include<stdlib.h>#define ElemType char 
#define MaxSize 9typedef struct {ElemType data[MaxSize];int top;
}SqStack;void InitStack(SqStack& Q) {Q.top = -1;
}bool isEmpty(SqStack& Q) {if (Q.top == -1)return true;elsereturn false;
}bool Push(SqStack& Q, ElemType x) {if (Q.top + 1 == MaxSize)return false;Q.data[++Q.top] = x;return true;
}bool Pop(SqStack& Q, ElemType& x) {if (Q.top == -1)return false;x = Q.data[Q.top--];return true;
}//括号匹配算法
bool bracketCheck(char s[],int length) {SqStack Q;InitStack(Q);char topElem;for (int i = 0; i < length; i++) {if (s[i] == '(' || s[i] == '[' || s[i] == '{') {Push(Q, s[i]);}else {Pop(Q, topElem);if (s[i] == ')' && topElem == '(' || s[i] == ']' && topElem == '[' || s[i] == '}' && topElem == '{')continue;elsereturn false;}}if (!isEmpty(Q))return false;return true;
}int main() {char s1[6] = { '(','(','[',']',')' };char s2[4] = { '(','{',']' };char s3[7] = { '(','[','{','}',']',')'};printf("%d\n",bracketCheck(s1, 5));printf("%d\n", bracketCheck(s2, 3));printf("%d\n", bracketCheck(s3, 6));
}

3.2 表达式求值

3.2.1 三种算术表达式
  • 中缀表达式

    就是我们日常所用的表达式。

    由操作符、界限符、操作数组成。

    • 运算符在两个操作数中间。
  • 后缀表达式(逆波兰式)

    运算符在两个操作数后面。

  • 前缀表达式(波兰式)

    运算符在两个操作数前面。

3.2.2 后缀表达式
A.中缀转后缀
  • 手算方法

    1.确定中缀表达式中各运算符的运算顺序。

    2.选择下一个运算符,按**【左操作数 右操作数 运算符】方式组合成新的操作数**。

    3.如果还有运算符没被处理,就继续第2步。

    • 注:运算顺序不唯一,对应的后缀表达式也不唯一,但机算是左优先原则。

    • 左优先原则:只要左边的运算符能先计算,就优先算左边。(可确保运算顺序唯一)

  • 机算

    初始化一个栈(用于保存暂时不能确定运算顺序的运算符)

    从左往右处理各元素,直到末尾,可能遇到以下三种情况:

    • 1.遇到操作数

      直接加入后缀表达式;

    • 2.遇到界限符

      遇到‘(’直接入栈;

      遇到‘)’依次弹出栈内运算符并加入后缀表达式,直到弹出‘(’;

    • 3.遇到运算符

      依次弹出栈中优先级高于或等于当前运算符的所有运算符,加入后缀表达式,

      若碰到‘(’或栈空停止,

      再把当前运算符入栈。

  • 中缀转后缀完整代码

    #include<stdio.h>
    #include<string.h>#define ElemType char
    #define MaxSize 99typedef struct {ElemType data[MaxSize];int top;
    }SqStack;void InitStack(SqStack& Q) {Q.top = -1;
    }bool isEmpty(SqStack& Q) {if (Q.top == -1)return true;elsereturn false;
    }bool Push(SqStack& Q, ElemType x) {if (Q.top + 1 >= MaxSize)return false;Q.data[++Q.top] = x;return true;
    }bool Pop(SqStack& Q, ElemType& x) {if (Q.top == -1)return false;x=Q.data[Q.top--];return true;
    }//运算符优先级判断
    int Priority(char x) {if (x == '-' || x == '+')return 1;else if (x == '*' || x == '/')return 2;else if (x == '(') return 0;return -1; 
    }//中缀转后缀
    //in是待转换的中缀表达式,suf是转换后的前缀表达式
    void in2suf(char in[], char suf[]) {//初始化一个栈SqStack Q;InitStack(Q);int isuf = 0;//suf数组下标char x;//从左往右遍历各元素for (int i = 0; i < strlen(in); i++) {if (in[i] >= '0' && in[i] <= '9') //遇到操作数。{suf[isuf++] = in[i]; //直接加入后缀表达式}else if (in[i] == '(') //遇到‘(’{Push(Q, in[i]); //直接入栈}else if (in[i] == ')')  //遇到‘)’{Pop(Q, x); //依次弹出栈内运算符while (x != '(') {suf[isuf++] = x; //并加入后缀表达式Pop(Q, x);}	}else //遇到运算符{ //依次弹出栈中优先级高于或等于当前运算符的所有运算符while (!isEmpty(Q)&&Priority(in[i]) <= Priority(Q.data[Q.top])) {if (Q.data[Q.top] == '(')break; //若碰到‘(’或栈空停止Pop(Q, x);suf[isuf++] = x; //加入后缀表达式}Push(Q, in[i]); //当前运算符入栈}}while (!isEmpty(Q)){Pop(Q, x);suf[isuf++] = x;}suf[isuf] = '\0';
    }int main() {char in[] = "1+5*(2+3)/(4-2)+3*1";char suf[MaxSize];in2suf(in, suf);printf("%s\n", in);printf("%s\n\n", suf);return 0;
    }
    

    在这里插入图片描述

B.后缀表达式的计算
  • 手算

    从左往右扫描,遇到一个运算符,就让运算符前面最近的两个操作数执行对应运算,合并为一个操作数。

  • 机算

    用栈实现后缀表达式的计算:

    1.从左往右扫描下一个元素,直到处理完所有元素;

    2.若扫描到操作数则压入栈,并返回第1步,否则执行第3步;

    3.若扫描到运算符,则弹出两个栈顶元素,执行相应运算,运算结果压回栈顶,回到第1步。

  • 后缀表达式求值 完整代码

    #define  _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<string.h>#define ElemType int
    #define MaxSize 99typedef struct {ElemType data[MaxSize];int top;
    }SqStack;void InitStack(SqStack& Q) {Q.top = -1;
    }bool isEmpty(SqStack& Q) {if (Q.top == -1)return true;elsereturn false;
    }bool Push(SqStack& Q, ElemType x) {if (Q.top + 1 >= MaxSize)return false;Q.data[++Q.top] = x;return true;
    }bool Pop(SqStack& Q, ElemType& x) {if (Q.top == -1)return false;x = Q.data[Q.top--];return true;
    }//后缀表达式求值
    int Computed_suf(char suf[]) {SqStack Q;InitStack(Q);int a, b,c;//从左往右扫描下一个元素,直到处理完所有元素for (int i = 0; i < strlen(suf); i++) {if (suf[i] >= '0' && suf[i] <= '9') { //若扫描到操作数则压入栈Push(Q, suf[i]-'0');}else { //若扫描到运算符,则弹出两个栈顶元素,执行相应运算,运算结果压回栈顶Pop(Q, b);Pop(Q, a);if (suf[i] == '+') {c = a + b;}else if (suf[i] == '-') {c = a - b;}else if (suf[i] == '*') {c = a * b;}else if (suf[i] == '/') {c = a / b;}Push(Q, c);}}return Q.data[Q.top];
    }int main() {char s[] = "1523+*72-/+31*+"; //1+5*(2+3)/(7-2)+3*1=9printf("%d", Computed_suf(s));return 0;
    }
    
3.2.3 前缀表达式
A.中缀转前缀
  • 手算

    1.确定运算顺序;

    2.选择下一个运算符,按【运算符 左操作数 右操作数】的方式组合成新操作数;

    3.如果还有运算符没被处理,重复第2步。

    • 右优先原则:只要右边运算符能先计算,就优先算右边。

B.前缀表达式的计算

用栈实现前缀表达式的计算:

1.从右往左扫描下一个元素,直到全部处理完;

2.若扫描到操作符则压入栈,返回第1步,否则执行第3步;

3.遇到运算符,弹出两个栈顶元素,执行相应运算,运算结果压回栈顶,返回第1步。

  • 注:在弹出的两个栈顶元素中,先出栈的是左操作数。
3.2.4 中缀表达式的求值
  • 方法

    用栈实现,就是中缀转后缀+后缀表达式计算

    1.初始化两个栈:操作数栈+运算符栈;

    2.若扫描到运算符或界限符,则按中缀转后缀相同逻辑压入运算符栈

3.3 递归中栈的应用

  • 函数调用特点

    最后被调用的函数最先执行结束(LIFO)

  • 调用函数时,需要用一个栈存储:

    1.调用返回地址;

    2.实参;

    3.局部变量。

  • 递归的精髓:

    将原始问题转换为属性相同但规模较小的小问题。

    大问题---->小问题

    • 但通常情况下,递归能减少代码量但效率不高
  • 在计算机中,用栈来解决函数的递归调用

    递归调用时,函数调用栈可称为“递归工作栈”,

    每进入一层递归,就将递归调用所需信息压入栈,

    每退出一层递归,就从栈顶弹出相应信息。

    • 通俗的说:函数调用,就是函数入栈;函数得到值,就是栈的弹出;

    • 缺点:递归太多可能导致栈溢出。

4.队列的应用

  • 树的层次遍历、图的广度优先遍历

  • 队列在计算机系统中的应用

    • 多队列的应用

      多个进程抢有限的系统资源时,FCFS(先来先服务)是常见策略。

    • 打印数据缓冲区

      在缓冲区中,用队列组织打印数据,

      可缓解主机与打印机速度不匹配问题。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图机器学习(3)-连接层面的特征工程

0 问题定义 通过已经连接去猜未知连接&#xff1a; 有两个思路&#xff1a;

CentOS下安装RabbitMQ

准备工作&#xff0c;更新yum源 正式环境慎用 yum update -y # 进入目录 cd /etc/yum.repos.d/ # 创建目录 mkdir backup # 默认源配备份 mv C* backup/ # 下载阿里云yum源 wget -O /etc/yum.repos.d/CenOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo # 清除旧…

【操作系统概念】 第7章:死锁

文章目录 0.前言7.1 系统模型7.2 死锁特征7.2.1 必要条件7.2.2 资源分配图 7.3 死锁处理方法7.4 死锁预防&#xff08;deadlock prevention&#xff09;7.4.1 互斥7.4.2 占有并等待7.4.3 非抢占7.4.4 循环等待 7.5 死锁避免&#xff08;deadlock-avoidance&#xff09;7.5.1 安…

docker离线搭建仓库

要在Docker中搭建本地仓库&#xff0c;可以按照以下步骤进行操作&#xff1a; 首先安装 Docker。根据不同的操作系统选择合适的版本并完成安装过程。打开命令行工具&#xff08;如Terminal或PowerShell&#xff09;&#xff0c;运行以下命令来创建一个新的容器并将其设置为本地…

牛客网 华为机试 坐标移动

本题是需要将输入的字符串&#xff0c;得到移动位置的信息&#xff0c;同时要判断移动信息的合法性。 所以我们可以考虑先通过正则表达式过滤得到正确的字符串。 正确的字符串应该以ADWS其中一个字母开头&#xff0c;然后后面接着1个或者2个&#xff08;0-9&#xff09;的数字。…

如何在小程序中绑定身份证

在小程序中绑定身份证信息是一项常见的需求&#xff0c;特别是在需要进行实名认证或者身份验证的场景下。通过绑定身份证信息&#xff0c;可以提高用户身份的真实性和安全性&#xff0c;同时也为小程序提供了更多的个性化服务和功能。下面就介绍一下怎么在小程序中绑定居民身份…

LVGL在VScode中安装模拟器运行配置笔记教程

1、LVGL模拟器工程搭建 LVGL(Light and Versatile Graphics Library,轻巧而多功能的图形库)是一个免费的开放源代码图形库,它提供创建具有易于使用的图形元素,精美的视觉效果和低内存占用的嵌入式GUI所需的一切。本文主要讲述如何实现在VScode中实现LVGL模拟器环境的搭建运行。…

element组件使用教程

首先在终端输入 npm i element-ui -S 下载完成后如何使用呢 在main.js文件中导入组件以及需要使用 import Vue from vue import { Button, Form, FormItem, Input, Message, Container, Header, Aside, Main, Menu, Submenu, MenuItem, MenuItemGroup } from element-uiVue.…

如何学习、上手点云算法(三):用VsCode、Visual Studio来debug基于PCL、Open3D的代码

写在前面 本文内容 以PCL 1.14.0&#xff0c;Open3D0.14.1为例&#xff0c;对基于PCL、Open3D开发的代码进行源码debug&#xff1b; 如何学习、上手点云算法系列&#xff1a; 如何学习、上手点云算法(一)&#xff1a;点云基础 如何学习、上手点云算法(二)&#xff1a;点云处理相…

Java项目:41 springboot大学生入学审核系统的设计与实现010

作者主页&#xff1a;源码空间codegym 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 本大学生入学审核系统管理员和学生。 管理员功能有个人中心&#xff0c;学生管理&#xff0c;学籍信息管理&#xff0c;入学办理管理等。 学…

WordPress建站入门教程:如何上传安装WordPress主题?

我们成功搭建WordPress网站后&#xff0c;默认使用的是自带的最新主题&#xff0c;但是这个是国外主题&#xff0c;可能会引用一些国外的资源文件&#xff0c;所以为了让我们的WordPress网站访问速度更快&#xff0c;强烈建议大家使用国产优秀的WordPress主题。 今天boke112百…

【C++】学习记录

一、第一个C程序 #include<iostream> using namespace std;int main() {cout << "Hello World!";return 0; } 二、数据类型、变量与常量、运算符 2.1 数据类型 2.2 变量与常量 2.3 运算符 三 、判断语句&#xff08;if-else、switch-case&#xff09; …

蓝桥杯物联网竞赛_STM32L071_11_知识体系的查漏与补缺

太久没学单片机了&#xff0c;再重新过一遍查漏补缺&#xff0c;对其中之前没怎么在意的&#xff0c;而现在又发觉的问题进行再分析与补充 1. debug serial wire是干什么用的 这个东西我勾选不勾选都对我的程序没有什么影响&#xff0c;我很好奇是干什么用的&#xff0c;网上查…

《Ubuntu20.04环境下的ROS进阶学习1》

一、vscode和超级终端Terminator 在上节我们已经逛了逛ROS官方应用商店和全球最大开源平台github。为了方便阅读代码和启动程序&#xff0c;本节我们来下载两个好用的app&#xff0c;当然是在Ubuntu上。 二、下载安装并运行vscode 1、下载vscode安装包 这里为了方便我们直接打…

职工医疗报销管理系统

目录 1 系统目标与范围说明... 0 1.1项目名称... 0 1.2问题说明... 0 1.3项目目标... 0 1.4项目范围... 0 1.5初步想法... 0 1.6可行性研究计划... 0 2 可行性分析报告... 1 2.1系统概述... 1 2.2可行性分析... 2 2.3结论意见... 2 3 项目开发计划... 2 3.1系统…

【电路笔记】-NPN晶体管

NPN晶体管 文章目录 NPN晶体管1、概述2、双极NPN晶体管配置3、NPN晶体管中的α和β关系4、示例5、共发射极配置1、概述 NPN 晶体管是三端三层器件,可用作放大器或电子开关。 在前面的文章中,我们看到标准双极晶体管或 BJT 有两种基本形式。 NPN(负-正-负)配置和PNP(正-负…

代码随想录 二叉树第四周

目录 617.合并二叉树 700.二叉搜索树中的搜索 98.验证二叉搜索树 530.二叉搜索树的最小绝对差 501.二叉搜索树中的众树 236.二叉树的最近公共祖先 617.合并二叉树 617. 合并二叉树 简单 给你两棵二叉树&#xff1a; root1 和 root2 。 想象一下&#xff0c;当你将其…

程序员未来发展之路-从入门到高手的成长轨迹

作为程序员&#xff0c;每个人的职业发展路径都是独特而富有挑战性的。从新手到专家&#xff0c;需要不断学习和实践&#xff0c;积累经验和技能。本文将带你探讨程序员职业发展的各个阶段以及关键要素&#xff0c;帮助你规划自己的职业发展之路。 一、新手阶段&#xff1a;夯…

fasta文件与fastq文件相互转化Python脚本

fa文件与fq文件互相转换 今天分享的内容是fasta文件与fastq文件的基本知识&#xff0c;以及通过Python实现两者互相转换的方法。 测序数据公司给的格式通常是fq.gz&#xff0c;也就是fastq文件&#xff0c;计算机的角度来说&#xff0c;生物的序列属于一种字符串&#xff0c;就…

2024/3/7—2575. 找出字符串的可整除数组

代码实现&#xff1a; int* divisibilityArray(char *word, int m, int *returnSize) {int n strlen(word);int *res (int*)malloc(sizeof(int) * n);long cur 0;for (int i 0; i < n; i) {cur (cur * 10 (word[i] - 0)) % m;res[i] (cur 0) ? 1 : 0;}*returnSize …