본문 바로가기
Study

(JAVA) JAVA Stack을 활용하여 infix-postfix 변환 및 계산

by Developer RyanKim 2019. 3. 15.
//1. 수식에서 첫번째 항목을 빼냅니다.

//2. 수식의 빼낸 항목이 피연산자라면 그대로 출력측으로 빼냅니다

//3. 수식의 빼낸 항목이 연산자라면 스택의 최상위 원소와 비교합니다.

//4. 빼낸 연산자의 우선순위가 스택의 최상위에 있는 원소보다 높으면 그대로 스택에 넣습니다.

//5. 그렇지 않다면 스택의 최상위 원소를 출력측으로 뺴내고 빼낸 연산자를 스택에 넣습니다.

//6. 단, 여는 괄호'('가 나오면 닫는괄호')'가 나올 때까지 스택에 남아있게 되며, 닫는괄호')'가 나타나면

그때까지 여는괄호'('보다 상위에 있는 모든 연산자를 출력측으로 빼냅니다.


정말 열심히 찾다가 어디선가 푸는 방식을 주석으로 코드에 넣은건데 출처를 잊었네요..

 이 방법대로 구현하면 infix -> postfix 변환이 잘됩니다.


public class InfixToPostfix {
private Stack stack;
public String infix = "";
public String inputToPostfix = "";

public InfixToPostfix() {
this.stack = new Stack<>();
}

public Stack getStack() {
return stack;
}

public int calcPostfix(){
for(int i = 0; i < inputToPostfix.length(); i++){
char token = inputToPostfix.charAt(i);
System.out.println("clac token : " + token);

if(isNumber(token)) stack.push(Character.digit(token,10));
else{
int n1 = (Integer) stack.pop();
int n2 = (Integer) stack.pop();
int operateRes = operateToken(token,n2,n1);

System.out.println("operateRes : " + operateRes);
stack.push(operateRes);
}
System.out.println(stack);
}
return (Integer)stack.pop();
}

private int operateToken(char operater,int n1, int n2){
switch (operater){
case '*' :
return n1 * n2;
case '/' :
return n1 / n2;
case '+' :
return n1 + n2;
case '-' :
return n1 - n2;
}
return 0;
}

public String getOutput(){
pushInStackForPostfix();
return inputToPostfix;
}
private void pushInStackForPostfix(){
for(int i=0; i < infix.length(); i++){
char token = infix.charAt(i);
System.out.println("token : " + token);

if(isNumber(token)){
inputToPostfix += token;
}else{
if(token == '('){
stack.push(token);
}else{
sortOperater(token);
}

System.out.println("==out==\n" + inputToPostfix);
}
}
clearStack();
}

private void sortOperater(char input){
System.out.println("==stack==\n" + stack.toString() + "\n ====");
if(stack.empty()){ stack.push(input); return;}

if(input == ')'){
while(!stack.isEmpty()){
char inClose = (Character) stack.pop();
if(inClose == '(') break;
inputToPostfix += inClose;
}
}else {
int inputGarde = getOperaterGrade(input);

while (!stack.isEmpty()) {
char prev = (Character)stack.pop();
if(prev == '('){
stack.push(prev);
break;
}
int prevGarde = getOperaterGrade(prev);

if (prevGarde >= inputGarde) {
inputToPostfix += prev;
} else {
stack.push(prev);
break;
}

}
stack.push(input);
}
}

public boolean isNumber(char token){
if('0' <= token && token <= '9')
return true;
else
return false;
}

private int getOperaterGrade(char operater){
int grade = 0;
switch (operater){
case '*' : case '/' : case '%':
grade = 2;
break;
case '+' : case '-' :
grade = 1;
break;
case '(' :
grade = 0;
break;
}
return grade;
}

private void clearStack(){
char token;
while(!stack.empty()){
token = (Character)stack.pop();
inputToPostfix += token;
}
}
}


작성하다가 힘이 빠져서 코드가 정리가 안된 부분도 많이 있을것 같습니다. 잘 걸러서 참고해주세요!


문제 풀면서 막혔던 부분은 

1. if else 조건을 줄 때 무슨조건을 먼저 검사할 것인지

2. Stack에 담을 객체의 타입 - 코드를 보시면 처음에 스택 하나로 postfix로 변환시에는 Char형을 넣어 사용하고 그후 계산을 할때는 Integer 형을 사용하기 때문에 두개를 변환하는 과정 등을 신경써야 했습니다.

3. while문의 종료 조건 - 반복문의 종료조건을 잘 확인하고 걸어야 했습니다.

4. 메소드를 나눌 단위 - 이 부분이 제일 어려웠습니다. 결국 나누다가 포기했지요... 잘게 쪼갤 수록 오히려 조건문이 더 많아지고 복잡해지는 느낌이 들었습니다.

댓글