트리 구조에서 연산식을 삽입하는 바법점 알려주세요
글쓴이: nidle / 작성시간: 토, 2003/04/19 - 9:03오후
제질문에 이렇게 답변을 해주셨습니다
그런데트리구조에 연산식을 삽입해야 하는 부분을 어떻게 해야하는지
잘모르겟어요,, 어떤 알고리즘으로 삽입을해야 되는지.. 책을 아무지찾아봐도
잘 나와있지가 않아서요
아직초보자라서 트리라는 구조도 이번에 알게 되네요
그러니 아직 삽입이나 삭제를 어떻게 해야되는지조차 모르겠어요
수식트리를 만드는 방법은 부모는 연산자 자식은 숫자 이런식으로
만들면 되구요. 숫자는 항상 단말노드가 되겠죠.
그리고 연산자의 우선순위에 따라서 부모 자식 관계가 됩니다.
(a + b) * c
이식을 수식 트리로 만들면?
....*....
.../\....
..+ c...
../\.....
.a b....
이트리를 prefix로 탐색하면서 찍어주면 prefix식 만들어 집니다.
트리 만드는 법은 한번 생각해 보세요
트리구조에 연산식을 삽입해야 하는 부분을 어떻게 해야하는지
잘모르겟어요,,
어떤 알고리즘으로 삽입을해야 되는지.. 책을 아무지찾아봐도
잘 나와있지가 않아서요
Forums:
infix -> postfix 변환 알고리즘을 응용하면 될 것 같은
infix -> postfix 변환 알고리즘을 응용하면 될 것 같은데요?
다른 거라면 트리의 형태라는 것..
스택에 infix -> postfix 알고리즘대로 연산자를 push, pop 하는 건 같고..
다른 거라면 심볼들을 트리로 만들어서 그 결과를 누적시킨다는게 다르군요..
말이 좀 이상하지만, 조금만 생각해보면 할 수 있습니다..
참고하세요
operator precedence를 생각해 주어야 하네요
post-fix로 변환해서 넣으면 되겠는데요?
binary tree의 구조는
struct Node {
enum {value, operator} type;
int attribute;
Node* left_child;
Node* right_child;
};
이런식으로 하면 될테구요 type이 operator일때는 operator마다 attribute값을 정해주세요.
(a+b) * c => (post-fix) ab+c*
ab+ -> left-child
c -> right-child
* -> this node
이렇게 할당해 주고
left-child는 reculsive 하게
a -> left-child
b -> right-child
+ -> this node
이렇게 top-down 방식으로 변환해 주는 알고리즘을 사용하면 될 거 같네요
EBNF 알고리즘도 있습니다.
위의 분들이 말씀 하신건 스택을 이용해서 postfix방식으로 접근 하신것 같은데요... 그렇게 해도 됩니다. 그렇게 해도 연산자 우선 순위를 고려해서 계산을 할 수 있습니다. 흠... 그런데 트리구조라면... 아마 이것을 원하고 있는게 아닐까 하네요....
다음은 그냥 생각나는 대로 마치 pseudo code처럼 쓴거라서 컴파일은 안되구요. 그냥 이해해 보세요. 어려운 것은 아닙니다.
식은 다음과 같이 표현됩니다.
<expression> = <term> {(+|-) <term>}
<term> = <factor> {(*|/) <factor>}
<factor> = id | <expression>
즉.
4+5*2+6-5는 위와 같은 알고리즘에 의해서...
expression + + -
term *
factor 4 5 2 6 5
와 같은 구조를 갖게 됩니다.
이때 트리구조를 갖게 되는데.... (사실은 위에 그게 트리구조로 그려야 되는뎅...)
리커시브하게 트리를 생성해 내게됩니다.
main()에서 expression()을 호출 하면 다시 term()을 호출하고 term()은 factor()을 호출하면서 계산이 됩니다.
lexeme[]라는 곳에 식이 들어 있다고 가정하면.... result에 계산값이 나오게 됩니다.
int main()
{
int index = 0;
int result;
Token = lexeme
;
result = expression();
return 0;
}
int expression()
{
int operand1, operand2;
operand1 = term();
while( lexeme
== '+' || lexeme
== '-' )
{
if (lexeme[index++] == '+') {
operand2 = term();
operand1 += operand2;
return operand1;
}
else if (lexeme[index++] == '-') {
operand2 = term();
operand1 -= operand2;
return operand1;
}
}
}
int term()
{
operand1 = factor();
while ( lexeme
== '*' || lexeme
== '/' )
{
if (lexeme[index++] == '*') {
operand2 = term();
operand1 *= operand2;
return operand1;
}
else if (lexeme[index++] == '/') {
operand2 = term();
operand1 /= operand2;
return operand1;
}
}
}
int factor()
{
int operand1;
operand1 = lexeme[index++];
return operand1;
}
대충 알고리즘만 이해하세요. 이대로 코딩 했다가는 오류 투성이일 겁니다.
좀더 제대로 만드려면 lexical analyzer라는 함수를 만들어야 할 겁니다. 그 함수는 lexeme[]에 있는 값들중 현재 index가 가르키는 값을 찾아서 숫자일때 까지 그 숫자들을 합하고, operator(+,-,*,/)라면 그 이제껏 합친 숫자를 리턴합니다.
제가 위에 쓴 코드는 그것 말고도 /계산을 할수 없습니다. /을 계산 하려면 분자와 분모값을 가지는 구조체를 정의하고 구조체를 리턴해야 할 겁니다. 마지막에 main()에서 그 구조체의 값을 게산하면 될 것이고.... 또 제가 쓴것은 괄호에 대한 연산도 하지 못합니다. 괄호를 계산하려면 factor()에서 괄호인 경우 다시한번 expression()을 호출해야 합니다.
그럼...
음 그러고 보니
yylex랑 parser 쓰면 간편하겠네요 ^^
댓글 달기