일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 큐
- 자료구조
- 30daysdowoonchallenge
- superstarjypnation
- 코드스테이츠
- web
- 프로토타입
- redux
- CSS
- UI
- useState
- level1
- 카카오
- javascript
- 생활코딩
- mysemester
- 회고
- 스택
- 프로그래머스
- Til
- UX
- 자바스크립트
- React
- Next.js
- REST_API
- html
- 해시테이블
- vercel
- 운영체제
- 백준
- Today
- Total
데굴데굴
[파이썬/실습] infix 수식을 postfix로 변환하기 본문
* class로 Stack을 정의한 후 코드를 작성했다.
* 수식에는 이항연산자만 사용한다고 가정한다.
어설프지만 infix와 postfix 그리고 스택은 아래 링크에 정리해두었다.
순차적 자료구조 & 스택 (stack)
순차적 자료구조 (Sequential data structures) 1. 배열, 리스트 - index로 임의의 원소에 접근 - 연산자 [ ] - 삽입 (append, insert) - 삭제 (pop, remove) 2. stack, queue, dequeue - 제한된 접근(삽입, 삭제)..
haruisshort.tistory.com
입력
1 + ( 2 + 3 ) / 4
출력
1 2 3 + 4 / +
Stack 클래스 정의
- push(value): 스택에 값을 넣음
- pop(): 스택의 가장 위에 있는 값을 삭제 후 리턴, 스택이 비어있으면 "Stack is empty"를 출력
- top(): 스택의 가장 위에 있는 값을 리턴, pop()과 마찬가지로 스택이 비어있으면 "Stack is empty"를 출력
- __len__(): 스택의 길이 출력
- isEmpty(): 스택이 비어있는지 아닌지 판단
class Stack:
def __init__(self):
self.items = []
def push(self, val):
self.items.append(val)
def pop(self):
try:
return self.items.pop()
except IndexError:
print("Stack is empty")
def top(self):
try:
return self.items[-1]
except IndexError:
print("Stack is empty")
def __len__(self):
return len(self.items)
def isEmpty(self):
return self.__len__() == 0
Postfix 수식 변환 코드 (infix_to_postfix 함수)
1. 공간 만들기
def infix_to_postfix(infix):
opstack = Stack()
outstack = []
opstack = 연산자가 오고나가는 스택
outstack = postfix 변환 결과가 저장되는 리스트
2. 문자열 형태로 입력받은 수식을 리스트로 변환하기
# 수식 토크나이징
token_list = infix.split()
infix에 문자열로 입력된 수식을 공백을 기준으로 나눠 리스트에 저장한다.
예)
infix = '2 * 3'
token_list = ['2', '*', '3']
3. 연산자의 우선순위 설정
prec = {}
prec['('] = 0
prec['+'] = 1
prec['-'] = 1
prec['*'] = 2
prec['/'] = 2
prec['^'] = 3
prec 이라는 이름의 딕셔너리를 생성하여 연산자별로 우선순위를 지정한다.
숫자가 높을수록 우선순위가 높은 것이다.
4. 반복문 작성
for token in token_list:
token_list의 token을 하나씩 살펴보며 postfix 변환 로직을 수행한다.
5. 경우 나누기
5-1. 왼쪽 괄호일 경우
if token == '(':
opstack.push(token)
왼쪽 괄호는 우선순위가 가장 낮다. 따라서 바로 스택에 들어가 대기하도록 push해준다.
5-2. 오른쪽 괄호일 경우
elif token == ')':
while opstack.top() != '(':
popped = opstack.pop()
outstack.append(popped)
opstack.pop()
opstack의 제일 위에 있는 값이 왼쪽 괄호일 떄까지 계속 pop하면서 pop할 때마다 리턴된 원소를 outstack에 집어넣는다.
왼쪽 괄호 차례에는 반복문이 정지되고 opstack에 아직 왼쪽 괄호가 남아있는 상태이므로 pop을 한 번 더 수행한다.
5-3. 연산자일 경우
가장 까다로웠던 부분이고 여기서 자꾸 생각했던대로 안 돼서 어려웠다.
elif token in '+-/*^':
# 스택이 비어있다면 바로 push
if opstack.isEmpty():
opstack.push(token)
# 그렇지 않다면 우선순위 비교하기
else:
if prec[token] <= prec[opstack.top()]:
while not opstack.isEmpty() and prec[token] <= prec[opstack.top()]:
popped = opstack.pop()
outstack.append(popped)
opstack.push(token)
else:
opstack.push(token)
1) 스택이 텅 빈 상태일 때에는 바로 push한다.
2) 그렇지 않고 스택에 어떤 연산자가 들어있는 상태라면 우선순위를 비교한다.
✔️경우 a. 스택의 가장 위에 있는 연산자가 token보다 우선순위가 높거나 같다.
- 스택의 가장 위에 있는 연산자, 즉 opstack.top()이 token보다 우선순위가 낮아질 때까지 계속 pop하고, pop한 원소를 outstack에 append한다. 그 후 token을 opstack에 push한다.
- 스택이 비어있을 때에는 pop하지 않도록 조건을 넣어준다.
✔️경우 b. 스택의 가장 위에 있는 연산자가 token보다 우선순위가 낮다.
- 바로 opstack에 push한다.
5-4. 피연산자일 경우
else: # operand일 때
outstack.append(token)
피연산자는 바로 outstack에 들어간다.
6. Stack에 남아있는 연산자 처리하기
# opstack 에 남은 모든 연산자를 pop 후 outstack에 append
while not opstack.isEmpty():
popped = opstack.pop()
outstack.append(popped)
위 과정을 다 수행하고 난 후에도 스택에는 여전히 연산자가 남아있을 수 있다. 따라서 그 연산자를 차례대로 pop하여 outstack에 넣는 코드를 작성해주어야 한다.
스택이 비어있을 때 pop을 수행하면 에러가 발생하므로 스택이 비어있지 않은 상태에만 수행하도록 while 조건문을 작성한다.
6. 리스트를 문자열로 변환하기
return " ".join(outstack)
.join(list)를 이용하면 리스트를 문자열로 만들 수 있다.
" ".join(outstack)은 문자 사이사이에 공백을 넣어준다.
만약 ":".join(outstack)으로 작성한다면 문자 사이사이에 콜론이 들어가게 된다.
최종 코드
'''
Infix to postfix
'''
class Stack:
def __init__(self):
self.items = []
def push(self, val):
self.items.append(val)
def pop(self):
try:
return self.items.pop()
except IndexError:
print("Stack is empty")
def top(self):
try:
return self.items[-1]
except IndexError:
print("Stack is empty")
def __len__(self):
return len(self.items)
def isEmpty(self):
return self.__len__() == 0
def infix_to_postfix(infix):
opstack = Stack()
outstack = []
# 수식 토크나이징
token_list = infix.split()
# 연산자의 우선순위 설정
prec = {}
prec['('] = 0
prec['+'] = 1
prec['-'] = 1
prec['*'] = 2
prec['/'] = 2
prec['^'] = 3
for token in token_list:
if token == '(':
opstack.push(token)
elif token == ')':
while opstack.top() != '(':
popped = opstack.pop()
outstack.append(popped)
opstack.pop()
elif token in '+-/*^':
# 스택이 비어있다면 바로 push
if opstack.isEmpty():
opstack.push(token)
# 그렇지 않다면 우선순위 비교하기
else:
if prec[token] <= prec[opstack.top()]:
while not opstack.isEmpty() and prec[token] <= prec[opstack.top()]:
popped = opstack.pop()
outstack.append(popped)
opstack.push(token)
else:
opstack.push(token)
else: # operand일 때
outstack.append(token)
# opstack 에 남은 모든 연산자를 pop 후 outstack에 append
while not opstack.isEmpty():
popped = opstack.pop()
outstack.append(popped)
# ... ... ...
return " ".join(outstack)
infix_expr = input()
postfix_expr = infix_to_postfix(infix_expr)
print(postfix_expr)
'CS > 자료구조' 카테고리의 다른 글
자료구조 큐 (Queue) (0) | 2022.06.30 |
---|---|
[파이썬/실습] postfix (후위식) 계산기 만들기 (0) | 2022.06.30 |
순차적 자료구조 & 스택 (stack) (0) | 2022.06.16 |
순차적 자료구조: 배열과 리스트 (0) | 2022.06.14 |
알고리즘 시간복잡도 Big-O (0) | 2022.06.14 |