第1关:STL模板之栈stack实例:中缀表达式转前缀表达式


任务描述

本关任务:熟练掌握STL模板库中栈stack的基本操作,并利用栈实现中缀表达式转化为前缀表达式。

相关知识

为了完成本关任务,你需要掌握:1.STL模板栈的基本操作,2.中缀表达式转前缀表达式。

STL模板栈的基本操作

C++ STL模板的栈通过现有的序列容器来实现的,默认使用双端队列deque的数据结构,也可以采用其他线性结构如:vectorlist等,前提是提供栈的入栈、出栈、栈顶元素访问和判断是否为空的操作。stack栈容器的C++标准头文件为stack。为了严格遵循栈元素后进先出原则,stack不提供元素的任何迭代器操作,提供的基础操作及实例如下:

  • empty判断栈是否为空,若空则返回true,否则返回false
  • size返回栈表当前的大小,即栈表里元素的个数;
  • top返回栈顶元素
  • push将元素压入栈顶
  • pop移除栈顶元素
 
  1. #include <iostream>
  2. #include <algorithm>
  3. #include <stack>
  4. int main (){
  5. std::stack<int> mystack; // 创建一个整型的栈表mystack
  6. int sum (0);
  7. for (int i=1;i<=10;i++) mystack.push(i); // 入栈
  8. std::cout << mystack.size() <<'\n'; // 栈大小
  9. while (!mystack.empty()){ // 判断栈是否为空
  10. sum += mystack.top(); // 获取栈顶元素
  11. mystack.pop(); // 移除栈顶元素
  12. }
  13. std::cout << "total: " << sum << '\n';
  14. return 0;
  15. }
中缀表达式转前缀表达式

算法思想:表达式中的对象为操作数和运算符,因此需要维护两个栈表:运算符栈和操作数(中间运算结果)栈,具体算法步骤如下。

  • (1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2
  • (2) 从右至左扫描中缀表达式;
  • (3) 遇到操作数时,将其压入S2
  • (4) 遇到运算符时,比较其与S1栈顶运算符的优先级:
  • (4-1) 如果S1为空,或栈顶运算符为右括号),则直接将此运算符入栈;
  • (4-2) 否则,若优先级比栈顶运算符的较高或相等,也将运算符压入S1
  • (4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;
  • (5) 遇到括号时:
  • (5-1) 如果是右括号),则直接压入S1
  • (5-2) 如果是左括号(,则依次弹出S1栈顶的运算符,并压入S2,直到遇到右括号为止,此时将这一对括号丢弃;
  • (6) 重复步骤(2)至(5),直到表达式的最左边;
  • (7) 将S1中剩余的运算符依次弹出并压入S2
  • (8) 依次弹出S2中的元素并输出,结果即为中缀表达式对应的前缀表达式。

例如,将中缀表达式1+((2+3)*4)-5转换为前缀表达式-+1*+2345的过程如下:

编程要求

本关的编程任务是补全右侧代码片段mainBeginEnd中间的代码,具体要求如下:

  • 读取中缀表达式,并基于栈的插入、删除等基本操作实现中缀表达式转化为前缀表达式,表达式中所有的操作数为单一的数字:0~9,运算符仅包含:+ - * ( )
测试说明

平台将自动编译补全后的代码,并生成若干组测试数据,接着根据程序的输出判断程序是否正确。

以下是平台的测试样例:

测试输入:1+((2+3)*4)-5 预期输出:-+1*+2345

输入格式:中缀表达式 输出格式:前缀表达式,末尾换行\n

//
//  main.cpp
//  step1
//
//  Created by ljpc on 2018/8/31.
//  Copyright © 2018年 ljpc. All rights reserved.
//

#include <iostream>
#include <stack>
#include <cstring>
#include <algorithm>
using namespace std;

int main(int argc, const char * argv[]) {

    // 请在这里补充代码,完成本关任务
    /********* Begin *********/
    string s;
    stack<char> s1;
    stack<char> s2;
    cin >> s;
    for ( int i = s.size()-1; i>=0; i--)//从右到左扫描
    {
        L1:
        if(s[i]>='0' && s[i]<='9')
        {
            s2.push(s[i]);
        }
       else
        {
            if(s[i]==')'||s1.empty())
            {
                s1.push(s[i]);
            }
            else if(s[i]=='(')
            {
                while(s1.top()!=')')
                {
                    s2.push(s1.top());
                    s1.pop();
                    goto L1;
                }
                s1.pop();
            }
            
            else if(s1.top()=='*' && (s[i]=='-'||s[i]=='+'))
            {
                s2.push(s1.top());
                s1.pop();
                goto L1;
            }
            else if(s1.top()=='('&& (s[i]=='+'||s[i]=='-'||s[i]=='*'))
            {
                s2.push(s1.top());
                s1.pop();
                goto L1;
            }
            else
            {
                s1.push(s[i]);
            }
        }
    }
    while(!s1.empty())
    {
        s2.push(s1.top());
        s1.pop();
    }
    while(!s2.empty())
    {
        printf("%c",s2.top());
        s2.pop();
    }

    /********* End *********/   
 
    return 0;
}

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值