算法题:四则运算(中缀式到后缀式的转换,值得思考的逆波兰式)

/*
字符串的四则运算。给出一个字符串,
包含0~9的数字和 + -*\/ ()的运算符,
- 仅代表减号不代表负数。举例如下:
输入:1 + 2 * (3 - 4)
*/

//哈哈,看到这道题,其实一点也不难,这个题根本就不用思考,
//当然是你明白算法之后,这里要用到的算法是逆波兰式。
//如果你有不明白的地方,可以上网搜逆波兰式。

/*
我的总结:计算机无法理解人类的正向思维,于是为了满足计算机的
思维,我们会反其道而行之,将操作符号放在操作数的后面,形成后缀
表达式,但是如果你能按百科上说的思维来做,那么轻而易举的就可以
得到答案。
*/

/*
1.根据表达式构造逆波兰表达式。
2.根据逆波兰表达式进行计算。
3.最终可以轻易的得到结果,我希望大家可以学习一下,共勉。
*/
//Start:

#include <iostream>
#include <string.h>
#include <stack>
using namespace std;

bool Is_Op(char ch)
{
    return (ch == ‘+‘ || ch == ‘-‘ || ch == ‘*‘ || ch == ‘/‘ || ch == ‘(‘ || ch == ‘)‘ || ch == ‘#‘);
}

bool Is_Com(char ch1, char ch2)
{
    //比较符号表达是的优先级。
    int i = 0;
    int j = 0;
    for (; "#+-*/()"[i] != ch1; i++){}
    for (; "#+-*/()"[j] != ch2; j++){}
    bool str[][7] = { 1, 0, 0, 0, 0, 0, 0,
        1, 1, 1, 0, 0, 0, 0,
        1, 1, 1, 0, 0, 0, 0,
        1, 1, 1, 1, 1, 0, 0,
        1, 1, 1, 1, 1, 0, 0,
        1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1 };
    return str[i][j];
}

int  Grial(char *&str)
{
    //先检测括号匹配是否正常吧。
    int flags = 0;
    char *fp = str;
    while (*fp != ‘\0‘)
    {
        if (*fp == ‘(‘)flags++;
        if (*fp == ‘)‘)flags--;
        fp++;
    }
    if (flags != 0)return -1;

    //开始构造波兰表达式。
    strcat(str, "#");
    char *p = str;
    char *q = str;
    stack<char> OP;
    OP.push(‘#‘);
    stack<string>  NM;
    int count = 0;
    string s;
    while (*p != ‘\0‘)
    {
        if (Is_Op(*p))
        {
            if (*p == ‘)‘)
            {
                while (OP.top() != ‘(‘)
                {
                    s = OP.top();
                    NM.push(s);
                    OP.pop();
                }
                if (OP.top() == ‘(‘)
                {
                    OP.pop();
                    p++;
                    continue;
                }
            }
            if (Is_Com(OP.top(), *p) && OP.top() != ‘(‘)
            {
                while (Is_Com(OP.top(), *p))
                {
                    s = OP.top();
                    NM.push(s);
                    OP.pop();
                    if (*p == ‘#‘ && OP.top() == ‘#‘)break;
                }
                OP.push(*p);
            }
            else
            {
                OP.push(*p);
            }
            p++;
        }
        else
        {
            while (!Is_Op(*p))
            {
                count = count * 10 + *p - ‘0‘;
                p++;
                if (*p == ‘\0‘ || *p == ‘#‘)break;
            }

            char buff[255];
            memset(buff, 0, sizeof(buff));
            itoa(count, buff, 10);
            s = buff;
            NM.push(s);
            count = 0;
        }
    }
    stack<string> numSt;

    while (NM.empty() == false)
    {
        numSt.push(NM.top());//逆序。
        NM.pop();
    }
    //目前为止已经构造好了逆波兰式,下面让我们来计算吧。

    stack<int> temp;
    while (numSt.empty() == false)
    {
        if (numSt.top() == "+" || numSt.top() == "-" || numSt.top() == "*" || numSt.top() == "/")
        {
            int a = temp.top();
            temp.pop();
            int b = temp.top();
            temp.pop();
            if (numSt.top() == "+")
            {
                temp.push(b + a);
            }
            else if (numSt.top() == "-")
            {
                temp.push(b - a);
            }
            else if (numSt.top() == "*")
            {
                temp.push(b*a);
            }
            else if (numSt.top() == "/")
            {
                temp.push(b / a);
            }
            numSt.pop();
        }
        else
        {
            temp.push(atoi(numSt.top().c_str()));
            numSt.pop();
        }
    }
    return temp.top();
}

int main()
{
    ;
    char *s = new char[20];
    memset(s, 0, sizeof(s));

    strcpy(s, "(1+2)*3-(1+2)/4+10");
    cout << Grial(s) << endl;

    strcpy(s, "1+2+4+(1*2)/3+4");
    cout << Grial(s) << endl;

    strcpy(s, "3+(4/2)+1+2-1*2");
    cout << Grial(s) << endl;

    strcpy(s, "(1+(2+3)*4)+2-0");
    //我还担心自己的双重括号没有考虑到,
    //没想到一次成功。
    cout << Grial(s) << endl;
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-10 04:00:50

算法题:四则运算(中缀式到后缀式的转换,值得思考的逆波兰式)的相关文章

算法题---带加减乘除和括号的单字母变量表达式转化成逆波兰式

#include <stdio.h> #include <stdlib.h> #include <malloc.h> #define STACK_INIT_SIZE 100 #define STACK_INCREAMENT 10 #pragma warning(disable:4996)//我用的vs2015,不加这句用scanf会报错(使用了unsafe的函数) typedef struct { //栈 char *base; char *top; int stack

使用逆波兰式进行表达式求值

中缀表达式及后缀表达式图解中说明了使用逆波兰式进行表达式求值的方法,这里使用C++进行实现.实现和原理讲解有一点不同,需要进一步进行细化. 关于将中缀表达式转换成后后缀表达式的规则: 规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分:若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于找顶符号(乘除优先加减)则栈顶元素依次出找并输出,并将当前符号进栈,一直到最终输出后缀表达式为止. 上面的规则转换成下面的执行规则: 1.遇到操作数:直接输出(添加到后缀

逆波兰式篇(后缀表达式)

一.逆波兰表示法(Reverse Polish notation,RPN,或逆波兰记法),是一种数学表达式方式,在逆波兰记法中,所有操作符置于操作数的后面.也称为后缀表达式. 二.一般算法 将一个普通的中序表达式转换为逆波兰表达式的一般算法是: 首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则. 读入一个中缀表达式,为了方便起见,可在其最右端追加一个最低优先级运算符(如:#号).(这样做的目的是,最后读入#号运算符时将运算符栈中所有运算符都输       出). 从左至右扫描该中

将中缀式转化为逆波兰式 (栈)

逆波兰式:Reverse Polish notation,RPN,,也叫后缀表达式,将运算符写在操作数之后 数据结构:两个栈S1和S2.S1临时存储运算符,S2存储最终结果. 算法:(1)若取出的字符是操作数,则分析出完整的运算数,该操作数直接送入S2栈(2)若取出的字符是运算符,则将该运算符与S1栈栈顶元素比较,如果该运算符优先级大于S1栈栈顶运算符优先级,则将该运算符进S1栈,否则,将S1栈的栈顶运算符弹出,送入S2栈中,直至S1栈栈顶运算符低于(不包括等于)该运算符优先级,则将该运算符送入

【LeetCode-面试算法经典-Java实现】【151-Evaluate Reverse Polish Notation(计算逆波兰式)】

[151-Evaluate Reverse Polish Notation(计算逆波兰式)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are +, -, *, /. Each operand may be an integer or another expression. Some

从中序表达式到逆序表达式(逆波兰式)(四则运算表达式求值)

本份代码需要两个栈.一个是符号栈,一个是数字栈. 输入中序表达式如9+(3-1)*3+10/2# #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<math.h> #define max 100 char ex[max]; /*存储后序表达式*/ /*函数功能:将中序表达式转化为后序表达式*/ void trans() { char str[max]; /*表达式字符串*/ char stack[max]; /*运

逆波兰式(后缀表达式)的计算

输入 :后缀表达式(可带浮点数) 输出:double型的计算结果 代码: #include <stdio.h> #include <stdlib.h> #include <malloc.h> #define ElemType double #define Stack_Init_Size 100 #define Increase_Size 10 #define MaxBuffer 10 typedef struct sqStack { ElemType *top; Ele

c# 逆波兰式实现计算器

语文不好,不太会组织语言,希望不要太在意. 如题,先简要介绍一下什么是逆波兰式  通常我们在写数学公式的时候  就是a+b+c这样,这种表达式称为中缀表达式,逆波兰式又称为后缀表达式,例如a+b 后缀表达式就为ab+ 而把中缀表达式转为逆波兰式也是很容易的,以下算法摘自百度百科 简要说一下栈,栈是一种先进后出的对象集合,可以把栈理解为一个桶,先进后出  Stack   Peek()是取出但是不剔除 做比较的时候用,Pop()是出栈,Push()入栈 首先需要分配2个栈,一个作为临时存储运算符的栈

js实现 - 逆波兰式

没有任何方法,除非你才华横溢. --艾略特 js实现 - 逆波兰式 2019-05-26 by 文科生 最近编译原理实验有涉及到逆波兰式,而且听闻有人在前端面试过程中被问到逆波兰式算法的实现,之前的离散数学课程中也有涉及到逆波兰式,作为一名前端人员,终于按耐不住想用js去实现求逆波兰式的算法.我查阅了大量的资料,发现有的算法虽然基本实现了对应的功能,但在细节处理方面略显不妥:而有的算法写的过于庞杂,想要完全读懂则代价昂贵,而且代码的臃肿不是因为算法本身复杂,而是加入了一些算符,这对理解算法本质是