`
Wangwei86609
  • 浏览: 3955 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Stack 表达式计算

阅读更多
package com.citi.ww03140.ds.exp;

import java.util.HashMap;
import java.util.Stack;

/*
3. 后缀表达式
后缀表达式也称为逆波兰式(Reverse Polish Notation, RPN),更加广为人知一些,和前缀表达式刚好相反,是将操作符号放置于操作数之后,比如2 + 3 * (5 - 1)用逆波兰式来表示则是:2 3 5 1 - * +。

逆波兰式的计算也是从左往右依次读取,当读到操作符时,将之前的两个操作数做计算,然后替换这两个操作数和操作符,接着读取,重复此步骤。对于这个表达式,读到5 1 -,得到4,然后读取乘号,取出前面的3和上一步的计算结果4,并计算,到12,接着读取加号+,计算2 12 +得到14,计算结束。

上面这个步骤可以很容易的用栈来实现:

从左往右依次读取表达式,如果是数字则将该数字压栈,如果是符号,则将之前的两个数字出栈,做计算后,将计算结果压栈,直到表达式读取结束。栈中剩下的一个数就是计算结果。

逆波兰式看起来像波兰式反过来,比如5 + 1的波兰式是+ 5 1,逆波兰式为5 1 +或者1 5 +。也很明显,逆波兰式并不是简单的将波兰式反过来,因为,减法和除法中减数和被减数、除数与被除数是不能交换的,即- 10 5和- 5 10就完全不一样。

4. 中缀表达式到后缀表达式的转换
因为通过后缀表达式来进行计算只需要一个栈即可,从硬件和软件上实现都是极为便利的,因此逆波兰式在计算机领域的应用更加广泛,因此将中缀表达式转换为逆波兰式非常重要。

依然仅仅使用栈就可以将中缀表达式转换成逆波兰式,转换过程如下:

从左往右遍历中缀表达式中的每个数字和符号,弱是数字就输出,成为逆波兰式的一部分; 如果是右括号,或者是其他符号并且比当前栈顶符号的优先级低,则栈顶元素依次出栈并输出; 然后将当前符号进栈,重复以上操作直到结束。

还是以2 + 3 * (5 - 1)为例:

首先读入数字2,直接将其输出,输出为2,栈为空
接着读入加号+,由于栈为空,因此将其进栈,输出为2,栈为+
接着读入数字3,直接将其输出,输出为2 3,栈为+
接着读入乘号*,比栈顶元素优先级高,进栈,输出为2 3,栈为+ *
读入左括号(,直接进栈,输出2 3,栈为+ * (
读入数字5,直接将其输出,输出为2 3 5,栈为+ * (
读入减号-,栈顶元素为左括号,进栈,输出为2 3 5,栈为+ * ( -
读入数字1,直接将其输出,输出为2 3 5 1,栈为+ * ( -
读入右括号,依次输出栈顶元素,直到左括号,括号不输出,输出2 3 5 1 -,栈为+ *
已经无元素可读,依次输出栈顶元素,直到栈为空,输出2 3 5 1 - * +,栈为空
这样可以仅仅使用栈,首先将中缀表达式转换为逆波兰式,然后用本文第3节中的方法对后缀表达式进行求值,整个过程使用栈来完成即可。

5. 表达式树与逆波兰式
还可以通过另外一种方法来将一个表达式转换成波兰式和逆波兰式,这种方法依赖与树,首先需要根据表达式构建成树,仍然以2 + 3 * (5 - 1)为例,下图是其表达式树。

6. 后缀表达式计算
将表达式,依次取出来,存入Stack,遇到运算符, 依次取2个stack top element 进行运算,并结果压stack,直到中只有最后一个元素



*/
public class StackExp {

    private final Stack<String> exps=new Stack<String>();

    private final Stack<String> oper=new Stack<String>();

    private final HashMap<String,Integer> mapping=new HashMap<String,Integer>();

    public StackExp(){
        mapping.put("+", 1);
        mapping.put("-", 1);
        mapping.put("*", 2);
        mapping.put("%", 2);
        mapping.put("/", 2);
        mapping.put("^", 3);
        mapping.put("(", 0);
        mapping.put(")", 0);
        mapping.put("|", -1);
    }

    public void transform(String expStr){
        char[] chs=expStr.toCharArray();
        for(int i=0;i<chs.length;i++){
            String s=String.valueOf(chs[i]);
            if(!mapping.containsKey(s)){
                exps.add(s);
            }else{
                if("(".equals(s)){
                    oper.add(s);
                }else if(")".equals(s)){
                    while(oper.size()>0 && !oper.peek().equals("(")){
                        exps.add(oper.pop());
                    }
                    oper.pop();
                }else{
                    if(oper.isEmpty()){
                        oper.add(s);
                    }else{
                        int curOp=mapping.get(s);
                        int topOp=mapping.get(oper.peek());
                        if(curOp>topOp){
                            oper.add(s);
                        }else{
                            do{
                                exps.add(oper.pop());
                            }while(oper.size()>0 && (curOp<=mapping.get(oper.peek())));
                            oper.add(s);
                        }
                    }
                }
            }
        }
        while(oper.size()>0){
            exps.add(oper.pop());
        }

        while(exps.size()>0){
            oper.add(exps.pop());
        }
        printExp();
        calculate();
        System.out.println(exps.toString());
    }

    private void calculate(){
        while(oper.size()>0){
            String op=oper.pop();
            if(mapping.containsKey(op)){
                double d=calculate(op,Double.parseDouble(exps.pop()),Double.parseDouble(exps.pop()));
                System.out.println(d);
                exps.push(String.valueOf(d));
            }else{
                exps.push(op);
            }
        }
    }

    private void printExp(){
        System.out.println(exps.toString());
    }

    private double calculate(String op,double d1, double d2){
        if(op.equals("+")){
            return d1+d2;
        }
        if(op.equals("-")){
            return d1-d2;
        }
        if(op.equals("*")){
            return d1*d2;
        }
        if(op.equals("/")){
            return d1/d2;
        }
        if(op.equals("%")){
            return d1%d2;
        }
        if(op.equals("^")){
            return Math.pow(d1, d2);
        }
        return 0;
    }

    public static void main(String[] args) {
        StackExp exp=new StackExp();
        exp.transform("(1+2)*3-5+8+(1+2)*3-5+8");
    }

}
分享到:
评论

相关推荐

    两种方式实现表达式计算

    在IT领域,表达式计算是计算机科学中的一个重要概念,它涉及到如何解析和处理数学或逻辑表达式以得出正确的结果。本文主要介绍了两种方法来实现表达式自动计算,这两种方法都是基于数据结构,特别是栈(Stack)的...

    后缀表达式计算

    后缀表达式,又称逆波兰表示法,是数学表达式的一种表示形式,它在计算领域具有重要的应用价值,尤其在算法设计和计算机科学中。后缀表达式的主要优点在于其简洁性和易于用栈来实现计算,这使得它成为解决计算问题的...

    中缀表达式计算C++实现

    - 在中缀表达式计算中,我们用一个栈存储运算符,另一个栈存储中间结果。 2. **算法步骤**: - 从左到右扫描中缀表达式。 - 遇到数字时,将其压入结果栈。 - 遇到运算符时,比较其优先级与栈顶运算符的优先级:...

    一个简单实用的表达式计算类

    本主题聚焦于一个“简单实用的表达式计算类”,这是一个用于解析和计算数学表达式的类,其源码用标准C++编写,且无需借助栈来实现。这一设计思路使得代码更加简洁高效,同时也减少了内存管理和性能优化的复杂性。 ...

    数据结构 c语言实现表达式计算

    在本项目中,“数据结构 C语言实现表达式计算”旨在使用C语言来设计一个计算器,该计算器能处理包含整数、小数以及括号的数学表达式。下面将详细介绍涉及的知识点。 1. **C语言基础**: C语言是一种强大的、低级的...

    数据结构课程设计 表达式计算

    2.赋值运算,即给某一变量赋值或赋计算表达式; 3.函数表达式求值,即运算量为变量。 4.运算量可以为实数,也可以为整数,只需简单修改宏定义。默认为实数运算。 二、数据结构设计 1. 算符优先法数据结构设计 本程序...

    用堆栈实现中缀转后缀表达式计算课程设计

    这个过程通常应用于计算机科学中的表达式计算,特别是编程语言的解析和计算。 首先,我们要理解中缀表达式和后缀表达式的基本概念。中缀表达式是我们常见的运算符位于操作数之间的表达式,如 `2 + 3 * 4`。而后缀...

    MFC计算器包含表达式计算

    MFC计算器项目是一个典型的桌面应用示例,它利用MFC库的强大功能实现了一个功能丰富的计算器,能够处理基本的数学运算以及更复杂的表达式计算。 首先,MFC计算器的核心是MFC框架。MFC提供了许多预定义的类,如...

    中缀表达式计算

    ### 中缀表达式计算知识点详解 #### 一、中缀表达式概述 中缀表达式是我们日常生活中最为常见的表达式形式,例如 \(8 + 5 \times (7 - 3)\)。在这种表达式中,操作符位于两个操作数之间。在计算这类表达式时,需要...

    栈数据类型之表达式计算

    在本主题“栈数据类型之表达式计算”中,我们将深入探讨如何利用栈这一数据结构来解决表达式计算的问题,尤其是对于逆波兰表示法(RPN,也称为后缀表达式)的计算。 栈在表达式计算中的应用主要体现在两个方面:...

    精选_基于C++实现的表达式计算_源码打包

    7. **堆栈(Stack)**: 堆栈数据结构在表达式计算中起到关键作用,特别是在后缀表达式(也称逆波兰表示法)的计算中。通过将运算符压入堆栈,可以按照后缀表达式规则进行计算,避免了优先级和括号的问题。 8. **...

    C语言后缀表达式计算.doc

    C 语言后缀表达式计算 C 语言后缀表达式计算是计算机科学中的一种算法,用于计算后缀表达式的值。后缀表达式是一种特殊的表达式,所有操作符都写在操作数的后面。例如,中缀表达式「a+b*c」对应的后缀表达式为「a b...

    C#用栈实现表达式计算

    首先,我们需要了解表达式计算的基本原理。在计算一个数学表达式时,我们通常遵循操作符的优先级,如括号内的运算优先于乘法和除法,乘法和除法又优先于加法和减法。这就是著名的“PEMDAS”规则(括号、指数、乘除、...

    前缀表达式转换和表达式计算设计报告

    - Stack相关的模块:定义结构体stack,以及初始化、压栈、弹栈和检查栈空的函数,用于后缀表达式的计算。 在测试阶段,应设计不同类型的测试用例,包括一般数据(常规输入)、边界数据(如空输入、只有一个元素的...

    根据表达式计算结果DLL库

    标题中的“根据表达式计算结果DLL库”是指一个动态链接库(DLL)项目,它包含一组函数,能够根据输入的字符串表达式计算出其数学结果。这个DLL库的核心功能是`double __stdcall ComputeFromString(char *s);`,该...

    多功能算术表达式计算类CMathString

    《CMathString:多功能算术表达式计算类详解》 在计算机编程中,处理数学表达式的计算是一项常见的任务。为了简化这一过程,开发者们通常会创建特定的类或函数来解析和评估算术表达式。CMathString就是这样一种工具...

    后缀表达式的计算_on81r_表达式求值_表达式计算_C++_计算表达式_源码.zip

    它通过消除括号和运算符优先级的问题,使得表达式计算变得简单且高效。在后缀表达式中,运算符位于其操作数之后,这与我们常见的中缀表达式(例如 `2 + 3 * 4`)不同,中缀表达式中运算符位于操作数之间。 在C++...

    用栈实现的中缀表达式计算

    总的来说,用栈实现的中缀表达式计算涉及到栈的特性、运算符的处理、括号匹配和控制流程等多个方面的知识,是一个很好的学习和实践数据结构与算法的实例。通过这个过程,你不仅可以深入理解栈的运作原理,还能掌握...

    java计算器!支持表达式计算啊!

    - 对于左括号“(”,立即压入运算符堆栈,而右括号“)”出现时,会连续弹出运算符堆栈中的运算符,直到遇到左括号,这对应于括号内的表达式计算。 - 运算符的优先级和结合性是关键,例如,乘法和除法的优先级高于...

    c#计算器(中缀表达式计算)

    在C#编程语言中,创建一个能够处理中缀表达式计算的计算器是一项常见的任务,它涉及到解析、评估和运算符优先级的管理。这个“c#计算器(中缀表达式计算)”项目的核心目标是将用户输入的带有操作符和数字的常规中缀...

Global site tag (gtag.js) - Google Analytics