찾다
Javajava지도 시간Java에서 후위 표현식 계산을 구현하는 방법

中缀表示法java实现

观察一个普通的算式:3+4*5

我们当然知道,应该先计算 4*5 再将这个结果和3相加,就能得到最后的结果。

如果是一个复杂一些的算式:3+4*((5-6)/7+8)

这依然难不倒我们,只要牢记()的优先级最高,然后是*/,最后是+-就没问题了,这就是通常的中缀表示法。

但是通过算法分析,这样的表达式,由于每一次都需要判断优先级,所以运行的时间应当是O(N^2)。

在表达式很长很复杂的时候,就需要一种更适合计算机的算法来计算了。

后缀表示法

简介

逆波兰表示法(Reverse Polish notation,RPN,或逆波兰记法),是一种是由波兰数学家扬·武卡谢维奇1920年引入的数学表达式方式,在逆波兰记法中,所有操作符置于操作数的后面,因此也被称为后缀表示法。

逆波兰记法不需要括号来标识操作符的优先级。逆波兰记法中,操作符置于操作数的后面。

例如表达“三加四”时,写作“3 4 +”,而不是“3 +4”。如果有多个操作符,操作符置于第二个操作数的后面,所以常规中缀记法的“3 - 4 + 5”在逆波兰记法中写作“3 4 - 5+”:先3减去4,再加上5。——维基百科逆波兰表示法词条。

这种表示法有以下特点:

  • 不需要使用括号。和中缀表达式不同,逆波兰表达式不需要遍历整个算式来寻找一对括号。

  • 逆波兰表达式的实现一般基于堆栈。在计算机中,堆栈这种数据结构具有极快的效率。运行时间是O(N)。

  • 不满足交换律。

逆波兰表达式的计算方式

例如2*3+4*5

你可以这么计算,2 和 3 相乘的和是 5,把这个数存起来,再计算 4*5 的值,存起来, 最后在计算两个存在一起的值。写出来是这样子的 2 3 * 4 5 * + 。这就是后缀或逆波兰记法。

采用堆栈实现的过程很简单,规则如下。

从头开始读取。读取到如果是数字,则将其压入栈中。如果是一个符号,就取两次栈顶的元素通过该符号进行计算,再把得到的数压入栈中。

Java实现

public class PRNCalculator {    
       public static double PRNCal(String PRN){
              Stack<Double> stack = new Stack<Double>();
              String[] ss = PRN.split(" ");
              for(int i = 0; i < ss.length; i++){
                     if(ss[i].matches("\\d")) stack.push(Double.valueOf(ss[i]));
                     if(ss[i].matches("[+|-|*|/]")){
                           double b = stack.pop();
                           double a = stack.pop();
                           if(ss[i].equals("+")) stack.push(a + b);
                           if(ss[i].equals("-")) stack.push(a - b);
                           if(ss[i].equals("*")) stack.push(a * b);
                           if(ss[i].equals("/")) stack.push(a / b);
                     }
              }
              return stack.pop();
       }
}

Test类

public class PRNTest {
       public static void main(String[] args) {
              String s = "2 3 * 4 5 * + ";
              double result = PRNCalculator.PRNCal(s);
              System.out.println("输入的逆波兰表达式:" + s);
              System.out.println("计算结果:" + result);
       }
}

打印结果:

输入的逆波兰表达式:2 3 * 4 5 * +
计算结果:26.0

与中缀记法的转换

和后缀表达式的计算方法类似,一个中缀记法转换到后缀记法,也可以利用堆栈来实现。

从头开始读取。如果读取到的是数字,将其输出。如果读取到的是符号,则判断该符号的优先级是否高于栈顶或栈为空,是,则压入栈中;否,则将栈顶输出并继续判断。如果读取到的是括号,”(“会直接被压入栈;在读取到”)”的时候,栈会一直弹出直到遇到”(“。下面是这个转换的Java实现。

package PRNCalculator;
import java.util.Stack;
public class PRNCalculator {
       public static String PRNTansf(String s){
              Stack<String> stack = new Stack<String>();
              String[] ss = s.split(" ");
              StringBuffer sb = new StringBuffer();
              for(int i = 0; i < ss.length; i++){
                     if(ss[i].matches("\\d")) sb.append(ss[i] + " ");
                     if(ss[i].matches("[+|-|*|/|(|)]")) {
                           if(stack.isEmpty()) {
                                  stack.push(ss[i]);
                           } else {
                                  if(ss[i].matches("[+|-]")) {
                                         while(!stack.isEmpty() && !stack.peek().matches("[(]")) sb.append(stack.pop()).append(" ");
                                         if(stack.isEmpty() || stack.peek().matches("[(]")) stack.push(ss[i]);
                                  }
                                  if(ss[i].matches("[*|/]")){
                                         while(stack.peek().matches("[*|/]") && !stack.peek().matches("[(]")) sb.append(stack.pop()).append(" ");
                                         if(stack.isEmpty() || stack.peek().matches("[(]") || stack.peek().matches("[+|-]")) stack.push(ss[i]);
                                  }
                                  if(ss[i].matches("[(]")) {
                                         stack.push(ss[i]);
                                  }
                                  if(ss[i].matches("[)]")){
                                         while(!stack.peek().matches("[(]")) sb.append(stack.pop()).append(" ");
                                         if(stack.peek().matches("[(]")) stack.pop();
                                  }
                           }
                     }
              }
              while(!stack.isEmpty()) sb.append(stack.pop()).append(" ");
              return sb.toString();
       }
}
* Test类*

package PRNCalculator;
public class PRNTest {
       public static void main(String[] args) {
              String s = "4 + 5 + 8 * ( 6 + 8 * 7 ) / 3 + 4";
              String PRN = PRNCalculator.PRNTansf(s);
              System.out.println("输入的表达式为:");
              System.out.println(s);
              System.out.println("输出的逆波兰表达式为:");
              System.out.println(PRN);
              double result = PRNCalculator.PRNCal(PRN);
              System.out.println("该表达式计算结果为:");
              System.out.println(result);
       }
}

打印结果:

输入的表达式为:
4 + 5 + 8 * ( 6 + 8 * 7 ) / 3 + 4
输出的逆波兰表达式为:
4 5 + 8 6 8 7 * + * 3 / + 4 +
该表达式计算结果为:
178.33333333333334

java后缀表达式的计算

实现方法

从左至右扫描表达式

遇到数字时,将数字压栈,遇到运算符时,弹出栈顶的两个数,计算并将结果入栈

重复2直到表达式最右端,最后运算得出的值即为表达式的结果

示例

计算后缀表达式的值:1 2 3 + 4 × + 5 -

从左至右扫描,将1,2,3压入栈;

遇到+运算符,3和2弹出,计算2+3的值,得到5,将5压入栈;

遇到4,将4压入栈

遇到×运算符,弹出4和5,计算5×4的值,得到20,将20压入栈;

遇到+运算符,弹出20和1,计算1+20的值,得到21,将21压入栈;

遇到5,将5压入栈;

遇到-运算符,弹出5和21,计算21-5的值,得到16为最终结果

代码实现

public class ReversePolishNotation {

    public static void main(String[] args) {
        String notation = "10 2 3 + 4 * + 5 -";
        ReversePolishNotation reversePN = new ReversePolishNotation();
        Stack<Integer> numStack = new Stack<>();
        //以空格分隔上述表达式,存到数组中
        String[] s = notation.split(" ");
        //遍历数组
        for (int i = 0; i < s.length; i++) {
            if (!reversePN.isOperator(s[i])){
                //如果不是运算符,则压栈
                numStack.push(Integer.parseInt(s[i]));
            } else {
                //为运算符,则取出栈顶的两个数字进行运算
                int result = reversePN.calculation(numStack.pop(), numStack.pop(), s[i]);
                //将结果压栈
                numStack.push(result);
            }
        }
        //循环结束,栈中仅剩的一个元素及为结果
        System.out.println(numStack.pop());
    }
    //判断是否是运算符
    public boolean isOperator(String oper){
        return oper.equals("+") ||oper.equals("-")  ||oper.equals("*")  ||oper.equals("/") ;
    }
    //计算
    public int calculation(int num1, int num2, String oper){
        switch (oper){
            case "+":
                return num2 + num1;
            case "-":
                return num2 - num1;
            case "*":
                return num2 * num1;
            case "/":
                return num2 / num1;
            default:
                return 0;
        }
    }
}

위 내용은 Java에서 후위 표현식 계산을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명
이 기사는 亿速云에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제
고급 Java 프로젝트 관리, 구축 자동화 및 종속성 해상도에 Maven 또는 Gradle을 어떻게 사용합니까?고급 Java 프로젝트 관리, 구축 자동화 및 종속성 해상도에 Maven 또는 Gradle을 어떻게 사용합니까?Mar 17, 2025 pm 05:46 PM

이 기사에서는 Java 프로젝트 관리, 구축 자동화 및 종속성 해상도에 Maven 및 Gradle을 사용하여 접근 방식과 최적화 전략을 비교합니다.

적절한 버전 및 종속성 관리로 Custom Java 라이브러리 (JAR Files)를 작성하고 사용하려면 어떻게해야합니까?적절한 버전 및 종속성 관리로 Custom Java 라이브러리 (JAR Files)를 작성하고 사용하려면 어떻게해야합니까?Mar 17, 2025 pm 05:45 PM

이 기사에서는 Maven 및 Gradle과 같은 도구를 사용하여 적절한 버전 및 종속성 관리로 사용자 정의 Java 라이브러리 (JAR Files)를 작성하고 사용하는 것에 대해 설명합니다.

카페인 또는 구아바 캐시와 같은 라이브러리를 사용하여 자바 애플리케이션에서 다단계 캐싱을 구현하려면 어떻게해야합니까?카페인 또는 구아바 캐시와 같은 라이브러리를 사용하여 자바 애플리케이션에서 다단계 캐싱을 구현하려면 어떻게해야합니까?Mar 17, 2025 pm 05:44 PM

이 기사는 카페인 및 구아바 캐시를 사용하여 자바에서 다단계 캐싱을 구현하여 응용 프로그램 성능을 향상시키는 것에 대해 설명합니다. 구성 및 퇴거 정책 관리 Best Pra와 함께 설정, 통합 및 성능 이점을 다룹니다.

캐싱 및 게으른 하중과 같은 고급 기능을 사용하여 객체 관계 매핑에 JPA (Java Persistence API)를 어떻게 사용하려면 어떻게해야합니까?캐싱 및 게으른 하중과 같은 고급 기능을 사용하여 객체 관계 매핑에 JPA (Java Persistence API)를 어떻게 사용하려면 어떻게해야합니까?Mar 17, 2025 pm 05:43 PM

이 기사는 캐싱 및 게으른 하중과 같은 고급 기능을 사용하여 객체 관계 매핑에 JPA를 사용하는 것에 대해 설명합니다. 잠재적 인 함정을 강조하면서 성능을 최적화하기위한 설정, 엔티티 매핑 및 모범 사례를 다룹니다. [159 문자]

Java의 클래스로드 메커니즘은 다른 클래스 로더 및 대표 모델을 포함하여 어떻게 작동합니까?Java의 클래스로드 메커니즘은 다른 클래스 로더 및 대표 모델을 포함하여 어떻게 작동합니까?Mar 17, 2025 pm 05:35 PM

Java의 클래스 로딩에는 부트 스트랩, 확장 및 응용 프로그램 클래스 로더가있는 계층 적 시스템을 사용하여 클래스로드, 링크 및 초기화 클래스가 포함됩니다. 학부모 위임 모델은 핵심 클래스가 먼저로드되어 사용자 정의 클래스 LOA에 영향을 미치도록합니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
4 몇 주 전By尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

SublimeText3 Linux 새 버전

SublimeText3 Linux 새 버전

SublimeText3 Linux 최신 버전

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

ZendStudio 13.5.1 맥

ZendStudio 13.5.1 맥

강력한 PHP 통합 개발 환경

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse를 SAP NetWeaver 애플리케이션 서버와 통합합니다.

에디트플러스 중국어 크랙 버전

에디트플러스 중국어 크랙 버전

작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음