四则计算机实现(C++)(堆栈的应用)

news2025/1/18 9:41:34

算法要求:

  1. 输入一个数学表达式(假定表达式输入格式合法),计算表达式结果并输出。
  2. 数学表达式由单个数字和运算符“+”、“-”、“*”、“/”、“(、) ”构成,例如 2 + 3 * ( 4 + 5 ) - 6 / 4。
  3. 变量、输出采用整数,只舍不入。

图解算法思想:

1、图中1、2、3、4~~表示操作的前后顺序

2、图中橙色栈用来处理数字,黄色用来处理运算符。

3、本图实际上将中缀转后缀、后缀求值两步整合在一起  

最后一步执行:取出‘-’,然后43-6=37,作为最后结果。

 

程序思想流程图:

 

代码如下:

【实验全部代码】
#include <iostream>
#include <string>
using namespace std;

// 写一个栈的模板函数,因为下面需要用到 int 和 char 两种 stack 类型,且方法一样
template <class T>
class Stack {
private:
    T data[1001];
    int size; // 同时承担 top 的作用

public:
    Stack() {
        size = 0;
    }
    ~Stack() {
        size = 0;
    }
    T pop() {//出栈
        size--;
        return data[size];
    }
    void push(T a) {//入栈
        data[size++] = a;
    }
    T front() {//返回栈顶元素
        return data[size - 1];
    }
    void clear() {//清除栈中元素,非物理清除,仅逻辑清除
        size = 0;
    }
    bool empty() {//判空
        return (size == 0);
    }
};

// 中序转后序函数
string inToSuffix(string s) {
    string result = "";
    int size = s.size();
    Stack<char> a;
    for (int i = 0; i < size; i++) {
//对括号的处理
        if (s[i] == '(') {
            a.push(s[i]);
        } else if (s[i] == ')') {
            if (!a.empty()) {
                char t = a.pop();
                while (t != '(' && !a.empty()) {
                    result.push_back(t);
                    t = a.pop();
                }
            }
//加减乘除的处理
        } else if (s[i] == '+' || s[i] == '-') { // 加减的等级是最低的
            while (!a.empty()) {
                if (a.front() == '(') {
                    break;
                } else { // 加减和乘除的处理方式一样,都是弹出
                    result.push_back(a.pop());
                }
            }
            a.push(s[i]);
        } else if (s[i] == '*' || s[i] == '/') {
            while (!a.empty()) {
                if (a.front() == '(') {
                    break;
                } else if (a.front() == '*' || a.front() == '/') { // 仅仅乘除被弹出,加减留在里面
                    result.push_back(a.pop());
                } else
                    break; // 如果遇到加减,则要直接 break,否则死循环
            }
            a.push(s[i]);
//数字的处理
        } else if (s[i] >= '0' && s[i] <= '9') {
            result.push_back(s[i]);
        } else {
            cout << "存在非法输入" << endl;
            break;
        }
    }
    while (!a.empty()) { // 最后要把栈中所有东西一一输出
        result.push_back(a.pop());
    }
    return result;
}

int suffix_print(string s) { // 后缀表达式核心就在于运算顺序,所以中缀中的括号在后缀中已经转化为数字和运算的前后顺序
    Stack<int> a;
    int size = s.size();
    for (int i = 0; i < size; i++) {
        if (s[i] >= '0' && s[i] <= '9')
            a.push(s[i] - '0');
        else {
            int s2 = a.pop();
            int s1 = a.pop();
            if (s[i] == '*') {
                a.push(s1 * s2);
            } else if (s[i] == '+') {
                a.push(s1 + s2);
            } else if (s[i] == '/') {
                a.push(s1 / s2);
            } else {
                a.push(s1 - s2);
            }
        }
    }
    return a.front();
}

int main() {
    cout << "Input" << endl;
    string input;
    cin >> input;
    cout << "Output" << endl;
    string inpute1 = inToSuffix(input);
    cout << "=" << suffix_print(inpute1) << endl;
    cout << "End";
    return 0;
}



感悟与算法分析: 

本题是实现计算器的制作。可以分为三个子问题:括号作用在数据结构中的实现、如何将中缀表达式化为后缀表达式、如何将后缀表达式的值计算出来

针对

问题一:对于一个表达式,我们采用栈的方式去存储。那么如何用栈来处理括号问题呢?

  1. 遇到括号则判断是否是哪一类型括号
  2. 如果是左括号则直接压入栈,后续将括号内的符号一一压入,期间这些符号也可以弹出,但是左括号一直不弹出。直到遇到右括号,则左括号上面以及左括号本身都要一并弹出。但是左括号并不输出、同时右括号并不压入栈。
  3. 如果右括号遇到但是栈中所有元素都弹出也没有左括号则报错误。若是左括号到程序最后也没有弹出则报错误

问题二:如何将中缀表达式转化为后缀表达式只要遵循下面这几个要求即可。

  1. 利用栈结构来处理
  2. 遇到1~9的数字直接printf打印输出,栈仅仅记录运算符号。
  3. 遇到括号则分为左右两种括号按照问题一的要求来处理
  4. 遇到+-*/运算符则要先把栈中优先级等于或小于该运算符的一一弹出,然后把该运算符本身压入栈中。

所以本问题可以利用多次的if判断语句,将问题分为这几种情况分别按照要求去处理

问题三:后缀表达式的求值也同样分为以下几个步骤来处理即可。

  1. 同样需要栈,但是栈此时存放的是数字
  2. 遇到数字则直接压入栈
  3. 遇到一个运算符则取出栈顶的两个元素,按照先输出的在左边、后输出的在右边与该运算符进行计算,并将运算结果重新压回栈中
  4. 在后缀表达式结束后,将栈中的元素取出来即为最后的答案

综上来说本题考察的主要是波兰表达式和逆波兰表达式的转化,以及逆波兰表达式的计算。而这些计算借助的数据结构就是栈。程序在书写的过程中最需要注意的就是if、elseif的分类处理。有一些类处理中需要用break来退出,否则会让程序进入死循环。其他一些注意点都在程序注释中标明。

仅供参考,一定不要直接复制!!!查重很严的!!! 

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

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

相关文章

MySQL InnoDB Cluster

MySQL InnoDB Cluster 一、InnoDB Cluster 基本概述 MySQL InnoDB Cluster 为 MySQL 提供了一个完整的高可用解决方案。通过使用 MySQL Shell 提供的 AdminAPI,你可以轻松地配置和管理一组至少由3个MySQL服务器实例组成的 InnoDB 集群。 InnoDB 集群中的每个 MySQL 服务器实例…

linux无网络 无ip,显示网络未连接

标题:linux无网络 无ip&#xff0c;显示网络未连接 参考blog&#xff1a;Linux无网络连接问题排查 首先我们发现ens33没有ip地址&#xff0c;说明这个接口并没有被分到ip&#xff1b; 我们可以通过手动方式来给ens33获得网络ip sudo dhclient ens33&#xff0c;之后再输入ifc…

大数据Hadoop-HDFS_元数据持久化

大数据Hadoop-HDFS_元数据持久化 &#xff08;1&#xff09;在HDFS第一次格式化后&#xff0c;NameNode&#xff08;即图中的主NameNode&#xff09;就会生成fsimage和editslog两个文件&#xff1b; &#xff08;2&#xff09;备用NameNode&#xff08;即图中的备NameNode&…

ChatGPT Plus/GPT4高级数据分析和插件功能详解

ChatGPT 在论文写作与编程方面也具备强大的能力。无论是进行代码生成、错误调试还是解决编程难题&#xff0c;ChatGPT都能为您提供实用且高质量的建议和指导&#xff0c;提高编程效率和准确性。此外&#xff0c;ChatGPT是一位出色的合作伙伴&#xff0c;可以为您提供论文写作的…

微服务实战系列之Redis(cache)

前言 云淡天高&#xff0c;落木萧萧&#xff0c;一阵西北风掠过&#xff0c;似寒刀。冬天渐渐变得更名副其实了。“暖冬”的说法有点言过其实了。——碎碎念 微服务实战系列之Cache微服务实战系列之Nginx&#xff08;技巧篇&#xff09;微服务实战系列之Nginx微服务实战系列之F…

Structured Streaming: Apache Spark的流处理引擎

欢迎来到我们的技术博客&#xff01;今天&#xff0c;我们要探讨的主题是Apache Spark的一个核心组件——Structured Streaming。作为一个可扩展且容错的流处理引擎&#xff0c;Structured Streaming使得处理实时数据流变得更加高效和简便。 什么是Structured Streaming&#…

数据结构中的二分查找(折半查找)

二分法&#xff1a;顾名思义&#xff0c;把问题一分为2的处理&#xff0c;是一种常见的搜索算法&#xff0c;用于在有序数组或这有序列表中查找指定元素的位置&#xff0c;它的思想是将待搜索的区间不断二分&#xff0c;然后比较目标值与中间元素的大小关系&#xff0c;然后确定…

Failed to connect to gitee.com port 443: Time out 连接超时提示【Bug已完美解决-鸿蒙开发】

文章目录 项目场景:问题描述原因分析:解决方案:解决方案1解决方案2:解决方案3:此Bug解决方案总结解决方案总结**心得体会:解决连接超时问题的三种方案**项目场景: 导入Sample时遇到导入失败的情况,并提示“Failed to connect to gitee.com port 443: Time out”连接超…

实现一个通讯录

目录 项目要求及功能实现 通讯录的代码实现 contact.h: contanct.c main.c 项目要求及功能实现 1、可以存放100个人的信息 2、每个人的信息 名字 性别 年龄 电话 地址 3、增加联系人 4、删除指定联系人 5、查找指定联系人 6、修改指定联系人 7、显示联系人信息 8、排…

运维笔记111

运维笔记 Navicat中查询指定字段名所在的表名tomcat设置JVM的初始堆内存修改catalina.sh文件修改完保存并关闭tomcat启动tomcat 查询数据库连接数查询是否存在死锁 Navicat中查询指定字段名所在的表名 SELECT * FROM information_schema.COLUMNS WHERE COLUMN_NAME‘替换成你要…

Redis-Redis 高级数据结构 HyperLogLog与事务

Redis 高级数据结构 HyperLogLog HyperLogLog(Hyper [ˈhaɪpə(r)] ) 并不是一种新的数据结构 ( 实际类型为字符串类 型) &#xff0c;而是一种基数算法 , 通过 HyperLogLog 可以利用极小的内存空间完成独立总数的统计&#xff0c;数据集可以是 IP 、 Email 、 ID 等。 如…

【brew】Mac上安装vue3

先安装node。 这里我从其他博客找的方案&#xff0c;原始脚本下载太慢了。 cnpm的安装&#xff1a; 让npm更快一点。 npm install -g cnpm --registryhttps://registry.npm.taobao.org安装vue脚手架 2.0版本&#xff1a;sudo npm install -g vue-cli 3.0版本&#xff1a; sud…

对话式数据需求激增,景联文科技提供高质量多轮对话数据定制采集标注服务

大模型的快速发展使得数据服务需求激增&#xff0c;产品整体处于供不应求状态。对话式数据集成为当下需求热点&#xff0c;人们对于更复杂、更真实的多轮对话数据需求不断增加&#xff0c;定制化服务占据市场需求主流。 通过对多轮对话数据的训练&#xff0c;模型可以更好地理解…

解析Top-K问题及堆排序算法

Top-K问题是在海量数据中找到最大或最小的K个元素&#xff0c;它在实际应用中非常常见&#xff0c;例如专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。在面对大规模数据时&#xff0c;直接对数据进行排序可能效率低下&#xff0c;因为排序的时间复杂度通常为O(n lo…

Notepad++批量添加引号

工作中经常会遇到这样情景&#xff1a;业务给到一批订单号&#xff0c;需要查询这批订单的某些字段信息。在where条件中需要传入这些订单号的数组&#xff0c;并且订单号用引号引起&#xff0c;用引号隔开。 字符串之间长度相同 可以按住CtrlAlt和鼠标左键选中区域&#xff0…

IDEA如何配置Git 遇到问题的解决

新建项目 点击 会变红 会生成.git隐藏文件 配置远程仓库路径&#xff1a;点击Manage Remotes&#xff1a;将远程仓库的链接放到这里&#xff1a; 得到如下样式&#xff1a; 此时提交到本地仓库 点击add&#xff0c;添加到暂存文件&#xff1a; 此时文件变绿&#xf…

力扣日记11.28-【二叉树篇】二叉树的最小深度

力扣日记&#xff1a;【二叉树篇】二叉树的最小深度 日期&#xff1a;2023.11.28 参考&#xff1a;代码随想录、力扣 111. 二叉树的最小深度 题目描述 难度&#xff1a;简单 给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点…

Gitee-PicGo-Typora

Gitee-PicGo-Typora 问题引出 问题1&#xff1a;根据相关法律法规和政策&#xff0c;您的部分文件因存在敏感信息而无法显示 就在昨晚&#xff0c; 我在记笔记的时候&#xff0c;发现之前配置的七牛云图床出了问题&#xff1a; 1、根据相关法律法规和政策&#xff0c;您的部…

联邦学习(Federated Learning)

联邦学习&#xff08;Federated Learning&#xff09;是一种保护用户隐私的分布式机器学习方法&#xff0c;在联邦学习中&#xff0c;模型的训练是在分布式的客户端设备上进行的&#xff0c;而模型的更新则是在中央服务器上进行的。联邦学习的目标是通过共享模型而不是原始数据…

C# 使用 Fody 监控方法执行时间

写在前面 在做性能调优的时候&#xff0c;经常需要跟踪具体方法的执行时间&#xff1b;通过插入Stopwatch的方案对代码的侵入性太高了&#xff0c;所以引入了 MethodTimer.Fody 类库&#xff0c;采用编译时注入的方式给方法动态加上Stopwatch 跟踪代码&#xff0c;只需要在目标…