1918번: 후위 표기식
첫째 줄에 중위 표기식이 주어진다. 단 이 수식의 피연산자는 알파벳 대문자로 이루어지며 수식에서 한 번씩만 등장한다. 그리고 -A+B와 같이 -가 가장 앞에 오거나 AB와 같이 *가 생략되는 등의
www.acmicpc.net
중위 표기로 주어진 계산식을 후위표기로 바꾸는 문제이다.
학부생때 배웠던 기억이 진짜 어렴풋이 나서 어떻게든 스택으로 해보려고 삽질 삽질을 하다가
종이 3장 낭비 후 규칙 발견해서 풀었다.
나는 정말 전위중위후위순회 문제가 싫다 ;
생각해낸 과정
Operand의 순서는 입력과 출력에서 바뀌지 않고 있는 것을 보고 힌트를 얻었다.
Operand는 만나자마자 출력하고, Operator를 스택에 넣어 순서를 바꿔주면 된다.
풀이
주어진 중위순회식을 한글자씩 now에 저장하며 반복문을 돈다.
- now가 Operand면 출력
- now가 Operator면
(stack에 담긴)지나온 연산자들 중 now보다 우선순위가 높은 연산자가 나중에 출력되면 안되니까,
stack에서 하나씩 peek해서 now보다 우선순위가 높거나 같으면(같을 경우 먼저 등장한 연산자를 먼저 출력해야함) pop하여 출력한다.
그리고 나서 now를 push해준다. - now가 괄호일 경우
'('이면 stack에 push한다.
')'이면 stack에서 '('가 나올때까지 pop하여 출력한다.
괄호도 stack에 들어가므로 우선순위를 " ( , ) < +, - < *, / " 이렇게 설정해줌
안그러면 2번조건에서 (를 출력하니까!
전체 코드
import java.io.*;
import java.nio.Buffer;
import java.util.*;
public class Main{
/*[골드3]Q1918 - 후위표기식*/
final static int OPERAND = 0;
final static int BRACKET = 1; //(,)
final static int OPERATOR_1 = 2; //+,-
final static int OPERATOR_2 = 3; //*,/
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
StringBuilder sb = new StringBuilder();
Stack<Character> operators = new Stack<>();
for(int i = 0; i<str.length();i++){
char now = str.charAt(i);
int nowType = getType(now);
switch(nowType){
case OPERAND:
//operand는 그냥 출력함
sb.append(now);
break;
case OPERATOR_1:
case OPERATOR_2:
//operator를 만나면 stack에 들어있는 연산자들 차례로 검사해서 now보다 우선순위 높거나 같으면 출력함
while(!operators.isEmpty() && getType(operators.peek())>=nowType){
sb.append(operators.pop());
}
//now보다 우선순위 높은 애들 다 나왔으면 now push
operators.push(now);
break;
case BRACKET:
//'('만나면 push함
if(now =='(') operators.push(now);
//')'만나면 '('나올때까지 pop해서 출력함 - 단, 괄호는 출력안함
if(now == ')'){
while(!operators.isEmpty() && operators.peek() != '('){
sb.append(operators.pop());
}
operators.pop(); //'('도 빼줌
}
break;
}
}
while(!operators.isEmpty()){
sb.append(operators.pop());
}
System.out.println(sb);
}
//연산자인지, 피연산자인지, 괄호인지 구분
private static int getType(char c){
if(c=='+'||c=='-') return OPERATOR_1;
else if(c=='*'||c=='/') return OPERATOR_2;
else if(c>='A' && c<='Z') return OPERAND;
else return BRACKET;
}
//c1이 우선이면 true, c2가 우선이면 false
private static boolean isPrior(char c1, char c2){
int p1, p2;
p1 = (c1 == '+' || c1 == '-')? 0:1;
p2 = (c2 == '+' || c2 == '-')? 0:1;
if(p1>p2) return true;
else return false;
}
}
'Java알고리즘' 카테고리의 다른 글
[개념] 순열, 조합, 부분집합 (0) | 2022.04.04 |
---|---|
[BOJ][Java]Q15591 - MooTube (0) | 2022.03.16 |
[BOJ][Java]Q4256 - 트리(전위순회,중위순회로 후위순회 구하기) (0) | 2022.03.14 |
[BOJ][Java]Q2233 - 사과나무 (0) | 2022.03.14 |
[BOJ][Java]Q3584 - 가장 가까운 공통 조상 (0) | 2022.03.14 |