음..
컴퓨팅 언어를 배우다보면 사칙연산 프로그램을 많이 만들어 보게된다.
(특히 조건분기문을 공부하기 위해서 말이죠)
그런데 이런 간단한 사칙연산 프로그램은 연산자가 여럿 쓰인 수식에는 적합하지 않다.
예를들어 (1+2*3)/4-5 같은 수식을 계산하려 한다면 사람이직접 연산자의 우선순위를 고려해서
2*3 입력 -> 1+ (2*3의 결과) -> .... 이렇게 나누어서 입력해줘야 한다.
그렇담 이런 수식을 한번에 계산해주도록 할 순 없을까?
라는 생각중에 나타난 것이 후위표기식(Postfix notation)에 관한 알고리즘들이다.
일단 후위표기식이 뭔지부터 보자.
1+2*3 이건 인간세상에서 많이 접하는 일반적인 수식이고 결과는 7이다.
그렇다면.. 1 2 3 * + 이건??
이상하게 생겼지만 이놈의 결과또한 7이다.
이렇게 연산자들이 피연산자의 뒤에 위치하는 수식을 후위표기식이라고 한다.
(우리가 늘 쓰는 첫번째 수식같은 경우는 중위표기식(infix notation)이라고 함. 전위표기식(prefix notation)이라는 것도 있다)
왜 이런 알아먹기 힘든 식으로 만들어놓느냐 한다면, 컴퓨터의 입장에서 보면 중위표기식보단 후위(또는 전위)표기식이 계산하기 더 쉽기때문이다.
(컴퓨터의 입장이라곤 해놨지만, 실상은 컴퓨터 프로그래머의 입장이 더 맞는거같다..)
그렇다면 어떤 규칙을 가지고 중위표기식을 후위표기식으로 만들어놓을까?
이런 고민끝에 에드거 다익스트라(Edsger Dijkstra) 라는 위대한 수학자(이자 프로그래머)가 후위표기법 변환 알고리즘을 고안해내었다.
그 과정을 적어보면,
1. 중위표기식에서 토큰을 읽어
2. 피연산자라면 결과에 출력하고,
3. 연산자라면,
예를 들어서 중위표기식인 (1+2*3)/5 을 후위식으로 바꿔보자
(단계마다 하나의 과정씩 순차적으로 적었으니 이해하긴 어렵지 않을것같다.)
두번째로 이렇게 변환된 후위식을 가지고 계산을 진행하면 결과를 얻을 수 있다.
후위식의 계산과정은 변환알고리즘보단 간단하다.
1. 후위표기식에서 토큰을 읽어
2. 피연산자라면 스택에 삽입하고
3. 연산자라면 스택에서 2회 팝하여 그 피연사자들을 연산자와 함께 계산한 후 결과를 스택에 다시 삽입한다.
4. 읽을거리가 더 없으면 마지막에 스택에 있는 요소가 수식의 계산결과이다.
마지막으로 위에 과정들을 토대로 후위식 변환 및 계산프로그램을 짜봤다.
위에있는 과정은 스택을 사용하는데 지난번에 만들어놓은 리스트스택을 쓰겠다.
그리고 후위식으로 만들어진 결과하나하나를 후위식 계산에 편리하게 링크드리스트에 연결시켰다
(굳이 리스트가 필요한건 아니지만, 중위식 -> 후위식 -> 계산 할 때 계속 토큰끊어가며 하는게 싫어서 그랬을 뿐)
아래 코드는 핵심이 되는 몇개 함수만 올려놓았다.
... 별로 효율적인 코드라고는 못하겠지만, 공부하는 입장에선 나름 볼만하다고 생각한다.
이 코드를 마무리로 이번 글은 끝
컴퓨팅 언어를 배우다보면 사칙연산 프로그램을 많이 만들어 보게된다.
(특히 조건분기문을 공부하기 위해서 말이죠)
그런데 이런 간단한 사칙연산 프로그램은 연산자가 여럿 쓰인 수식에는 적합하지 않다.
예를들어 (1+2*3)/4-5 같은 수식을 계산하려 한다면 사람이직접 연산자의 우선순위를 고려해서
2*3 입력 -> 1+ (2*3의 결과) -> .... 이렇게 나누어서 입력해줘야 한다.
그렇담 이런 수식을 한번에 계산해주도록 할 순 없을까?
라는 생각중에 나타난 것이 후위표기식(Postfix notation)에 관한 알고리즘들이다.
일단 후위표기식이 뭔지부터 보자.
1+2*3 이건 인간세상에서 많이 접하는 일반적인 수식이고 결과는 7이다.
그렇다면.. 1 2 3 * + 이건??
이상하게 생겼지만 이놈의 결과또한 7이다.
이렇게 연산자들이 피연산자의 뒤에 위치하는 수식을 후위표기식이라고 한다.
(우리가 늘 쓰는 첫번째 수식같은 경우는 중위표기식(infix notation)이라고 함. 전위표기식(prefix notation)이라는 것도 있다)
왜 이런 알아먹기 힘든 식으로 만들어놓느냐 한다면, 컴퓨터의 입장에서 보면 중위표기식보단 후위(또는 전위)표기식이 계산하기 더 쉽기때문이다.
(컴퓨터의 입장이라곤 해놨지만, 실상은 컴퓨터 프로그래머의 입장이 더 맞는거같다..)
그렇다면 어떤 규칙을 가지고 중위표기식을 후위표기식으로 만들어놓을까?
이런 고민끝에 에드거 다익스트라(Edsger Dijkstra) 라는 위대한 수학자(이자 프로그래머)가 후위표기법 변환 알고리즘을 고안해내었다.
그 과정을 적어보면,
1. 중위표기식에서 토큰을 읽어
2. 피연산자라면 결과에 출력하고,
3. 연산자라면,
스택 최상위 노드의 연산자부터 자기보다 낮은 우선순위의 연산자를 만날때까지 팝하여 출력한 후 자신을 푸쉬한다.
(즉, 현제 연산자보다 스택의 연산자의 우선순위가 높거나 같으면 팝하여 출력하며 이를 반복한는것)
(왼쪽괄호는 우선순위가 가장 낮지만, 예외적으로 무조건 스택에 삽입한다)
(즉, 현제 연산자보다 스택의 연산자의 우선순위가 높거나 같으면 팝하여 출력하며 이를 반복한는것)
(왼쪽괄호는 우선순위가 가장 낮지만, 예외적으로 무조건 스택에 삽입한다)
4. 오른쪽 괄호라면 최상위 노드부터 왼쪽괄호가 나올때 까지 팝 하면서 결과에 출력한다.
(왼쪽괄호는 제거하고 출력하지 않습니다.)
5. 더 읽을것이 없을때까지 반복한다.
의 다섯가지 과정으로 적을 수 있다.
이런 과정을 거치면 중위식이 후위식으로 변하며, 괄호도 사라지게 된다.(이것또한 후위식의 장점이라고도 할 수 있다.)
(왼쪽괄호는 제거하고 출력하지 않습니다.)
5. 더 읽을것이 없을때까지 반복한다.
의 다섯가지 과정으로 적을 수 있다.
이런 과정을 거치면 중위식이 후위식으로 변하며, 괄호도 사라지게 된다.(이것또한 후위식의 장점이라고도 할 수 있다.)
예를 들어서 중위표기식인 (1+2*3)/5 을 후위식으로 바꿔보자
(단계마다 하나의 과정씩 순차적으로 적었으니 이해하긴 어렵지 않을것같다.)
출력 스택
(
1 (
1 ( +
1 2 ( +
1 2 ( + *
1 2 3 ( + *
(오른쪽 괄호를 만남)
1 2 3 * ( +
1 2 3 * + (
1 2 3 * +
1 2 3 * + /
1 2 3 * + 5 /
1 2 3 * + 5 / (최종 결과)
1 (
1 ( +
1 2 ( +
1 2 ( + *
1 2 3 ( + *
(오른쪽 괄호를 만남)
1 2 3 * ( +
1 2 3 * + (
1 2 3 * +
1 2 3 * + /
1 2 3 * + 5 /
1 2 3 * + 5 / (최종 결과)
과정을 따라 해보면 별로 어렵지 않다.
두번째로 이렇게 변환된 후위식을 가지고 계산을 진행하면 결과를 얻을 수 있다.
후위식의 계산과정은 변환알고리즘보단 간단하다.
1. 후위표기식에서 토큰을 읽어
2. 피연산자라면 스택에 삽입하고
3. 연산자라면 스택에서 2회 팝하여 그 피연사자들을 연산자와 함께 계산한 후 결과를 스택에 다시 삽입한다.
4. 읽을거리가 더 없으면 마지막에 스택에 있는 요소가 수식의 계산결과이다.
마지막으로 위에 과정들을 토대로 후위식 변환 및 계산프로그램을 짜봤다.
위에있는 과정은 스택을 사용하는데 지난번에 만들어놓은 리스트스택을 쓰겠다.
그리고 후위식으로 만들어진 결과하나하나를 후위식 계산에 편리하게 링크드리스트에 연결시켰다
(굳이 리스트가 필요한건 아니지만, 중위식 -> 후위식 -> 계산 할 때 계속 토큰끊어가며 하는게 싫어서 그랬을 뿐)
아래 코드는 핵심이 되는 몇개 함수만 올려놓았다.
... 별로 효율적인 코드라고는 못하겠지만, 공부하는 입장에선 나름 볼만하다고 생각한다.
이 코드를 마무리로 이번 글은 끝
'Note..' 카테고리의 다른 글
이번에는,, (1) | 2011.08.14 |
---|---|
윈도우 폴더, 글자길이제한의 또다른 필요성?! (0) | 2011.08.14 |
내 코드 출력해주기 (0) | 2011.08.01 |
c# 맵에디터 (0) | 2011.05.18 |
12기 대상 C++강의 숙제(1) (0) | 2011.03.28 |