본문 바로가기
Baekjoon/[1] 자료구조

[백준] 1918번 후위 표기식 JAVA (자바) 풀이

by Poorm 푸름 2023. 7. 3.

문제 1918번

 : 수식은 일반적으로 3가지 표기법으로 표현


 : 연산자가 피연산자 가운데 위치하는 중위 표기법  ( 예: a+b )

   연산자가 피연산자 앞에 위치하는 전위 표기법 ( 예: +ab )

   연산자가 피연산자 뒤에 위치하는 후위 표기법 ( 예: ab+ )

 :  후위 표기식 장점은 순서를 적절히 조절하여 순서를 정해줄 수 있어서 괄호 등도 필요 없게 된다

 
:  중위 표기식을 후위 표기식으로 바꾸는 방법          a+b*c

    연산자의 우선순위에 따라 괄호로 묶기                  (a+(b*c))

    괄호 안의 연산자를 괄호의 오른쪽으로 옮기기      (a+bc*)

    마지막으로 또 +를 괄호의 오른쪽으로 고치기        abc*+

 
   예시 ) A+B*C-D/E   →    결과: ABC*+DE/- 



 [입력]

  

 :  첫째 줄에 중위 표기식이 주어진다
   
 :  피연산자는 알파벳 대문자, 알파벳 중복 X

 

 :  그리고 -A+B와 같이 -가 가장 앞에 오거나 AB와 같이 * 생략금지

 

 :  표기식은 알파벳 대문자와 +, -, *, /, (, ) 로 이루어진다 (길이는 100을 넘지 X)



 [출력]


 :  첫째 줄에 후위 표기식으로 바뀐 식을 출력



 [문제이해]

 

 : 스택에는 괄호와 연산자만 넣는다

 

 : 알파벳은 그때그때 바로바로 출력한다

 

 예)  입력 = A - B  * ( C + D ) 인 경우

 

입력순서
A 입력 - 입력 B 입력 * 입력 ( 입력  C 입력 + 입력 D 입력 ) 입력  끝
스   택
            + [( < +]   +      
        ( ( ( (    
      * [- < *]  *   * * * *  
  - - -  -   - - - -  
결    과
A A B A B A B A B C A B C A B C D A B C D + ABCD+*-

 

 [스택 연산]

 

  push(e)  스택의 맨 위에 요소 e 추가
  pop()  스택의 맨 위 요소를 삭제
  peek(s)  스택의 맨 위 요소를 삭제하지 않고 반환
  top()  스택 맨 위에 있는 데이터 값 반환
  isEmpty()  스택에 원소가 없으면 'True', 있으면 'False' 값 반환
  isFull()  스택에 원소가 없으면 'False', 있으면 'True' 값 반환

 

 [코드]

import java.io.*;
import java.util.*;
public class Main{
      static int priority(char c){
        if(c=='+' || c=='-')
            return 1;
         else if(c=='*' || c=='/')
             return 2;
         else
             return 0;
     }
     public static void main(String[] args)throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        Stack<Character> stack = new Stack<>();
        StringBuilder sb = new StringBuilder();
         
        String s = br.readLine();
         
        for(int i=0;i<s.length();i++){
            char c = s.charAt(i);
            
            if(c >= 'A') 
                sb.append(c);
                
            else if(c== '(')
                    stack.push(c);
            
            
             else if(c==')'){
                    while(stack.peek()!='('){ //스택 peek가 (일때 멈추란말
                        sb.append(stack.pop());
                    } // ( 전까지 다뽑아
                    stack.pop(); // ( 뽑아
                   
             }
            
            else{
                while (!stack.isEmpty() && priority(stack.peek()) >= priority(c)) {
                sb.append(stack.pop());
                }
            stack.add(c);
            }
        }
         
        while (!stack.isEmpty()) {
            sb.append(stack.pop());
        }
        bw.write(sb.toString());
        bw.flush();
    }
}

 

 [해설]

 :  static int priority(char c){  새로운 메서드 만들기
        if(c=='+' || c=='-')                                        
            return 1;                                                                       우선순위 (수가 클수록 높다)
         else if(c=='*' || c=='/')                                                       -   0    =     (
             return 2;                                                                      -   1     =    +,  -
         else                                                                                 -   2     =    *,  / 
             return 0;
      }

 ** 메서드(method)란? **

  - 문제를 처리하기 위한 방법으로 소스 코드로 묶어놓고 필요에 따라 호출하여 동작시키는 기능 

 :  Stack<Character> stack = new Stack<>();  스택선언

 :  StringBuilder sb = new StringBuilder();  문자 이어붙여야해서

 :  String s = br.readLine(); 첫째줄에 중위표기식 입력받기
         
 :  for(int i=0;i<s.length();i++){
             char c = s.charAt(i);  입력받은 문자들을 하나하나 뜯어보려고
            
             if(c >= 'A')  입력받은 문자 아스키 코드가 A이상 즉 알파벳이 나오면 바로 출력
                  sb.append(c);  해당문자 즉 알파벳 나오면 알파벳 바로 출력
                
             else if(c== '(')  입력받은 문자가 열린괄호 ( 이면 스택에 넣기
                   stack.push(c);
            
            
             else if(c==')'){ 입력받은 문자가 닫힌괄호 ) 일 경우
                    while(stack.peek()!='('){  peek가 (일때 멈추란 말, 다른말로 peek가 ( 아닐 동안만 동작
                        sb.append(stack.pop());  (를 스택의 peek로 만들어야하니까 스택에서 ( 직전까지 다뽑기 
                    } 뽑았던 애들 출력하기
                    stack.pop();  이제 스택의 peek는 (이다 이 열린괄호도 스택에서 버리기 대신 출력하진 않는다        
             }
            
             else{  여기는 알파벳도 괄호도 아닌 연산자들끼리만 보는 함수
                   while (!stack.isEmpty() && priority(stack.peek()) >= priority(c)) {  아까 지정한 메서드 참고
                       sb.append(stack.pop());  스택의 peek ≥ 새로 입력받는 문자(연산자) 비교해서 
                   }                                           peek 우선순위 더 높다면 peek 를 스택에서 빼내서 출력
                   stack.add(c);  peek의 우선순위가 더 낮다면 새로 입력받은 문자를 스택에 push 
            }
   }
         
 :  while (!stack.isEmpty()) { 
             sb.append(stack.pop());  스택 빌때까지 남은 연산자 모두 빼서 출력
     }

 :        bw.write(sb.toString());  출력
          bw.flush();
    

이제 풀어보러 갈께요 :)

 

https://www.acmicpc.net/problem/1918 

 

1918번: 후위 표기식

첫째 줄에 중위 표기식이 주어진다. 단 이 수식의 피연산자는 알파벳 대문자로 이루어지며 수식에서 한 번씩만 등장한다. 그리고 -A+B와 같이 -가 가장 앞에 오거나 AB와 같이 *가 생략되는 등의

www.acmicpc.net

* 독학으로 익히는 코딩이라 틀린 것이 있을 수 있습니다. 오류가 있다면 댓글을 통해 알려주세요. 감사합니다. *