이전 글과 이어집니다. 이진 트리의 연결 리스트를 통한 구현에 대한 내용입니다.
이전 글 보러가기
이진 트리를 탐색하기 위해 재귀적 방법을 사용하고자 합니다. 먼저 탐색 종류를 설명을 해보자면..
재귀식 탐색을 하기 때문에 노드가 아닌 서브트리로 작성한 것입니다!
이 정도로만 적고 바로 구현으로 들어가 보겠습니다.
void Inorder(BTreeNode* root) {
if (root != NULL) {
Inorder(root->left_child); // L
cout << root->item; // C
Inorder(root->right_child); // R
}
}
모든 과정이 재귀적 구조에 의해 진행됩니다.
void Preorder(BTreeNode* root) {
if (root != NULL) {
cout << root->item << " "; // C
Preorder(root->left_child); // L
Preorder(root->right_child); // R
}
}
void Postorder(BTreeNode* root) {
if (root != NULL) {
Postorder(root->left_child); // L
Postorder(root->right_child); // R
cout << root->item << " "; // C
}
}
지금까지 탐색을 재귀적 방법으로 했다면, 레벨 순서에 따른 탐색은 큐(Queue)를 이용합니다.
큐를 적용해보자면..
이렇게 할 수 있겠네요! 노드를 큐에서 제거할 때는 그 노드의 자식 노드를 왼쪽->오른쪽 순서로 큐에 등록합니다.
자세히 설명하자면, 차례대로 노드를 탐색 할 때 마다 탐색한 노드는 큐에서 제거합니다. 그리고 그의 자식들을 큐에 등록함으로써 순서대로 순회를 하게 되는 것입니다.
코드를 작성 해보자면 이렇게 되겠네요.
(큐를 정의하는 것은 생략합니다.)
void Levelorder(BTreeNode* root) {
Queue queue;
if (root == NULL) return;
InitQueue(&queue);
EnQueue(&queue, root);
while(!IsEmpty(&queue)) {
root = Peek(&queue);
DeQueue(&queue);
cout << root->item << " ";
if (root->left_child != NULL)
EnQueue(&queue, root->left_child);
if (root->right_child != NULL)
EnQueue(&queue, root->right_child);
}
}
이진 트리 탐색을 응용하는 방법에 대해 써보고자 합니다.
계산식을 표기하는 방법 중 중위 표기법(Infix Notation) 에 대해서 이를 적용할 수 있겠습니다.
중위 표기법이란
일반적인 수식의 표기법으로, 두 개의 피연산자 가운데에 연산자가 있는 구조입니다. X+Y 이런 식으로요!
예를 들어서 (7+4)*2-1
이라는 수식을 이진 트리로 만들어보면 다음과 같습니다.
이렇게 직관적인 형태로 표현이 가능합니다.
이걸 계산하는 원리에 대해서 설명하자면 우리가 위 계산식을 계산하는 과정과 같습니다.
1. 7 + 4
를 계산합니다.
2. 위의 계산 결과를 *
노드의 왼쪽 자식 노드로 지정합니다.
3. 11 * 2
를 계산합니다.
4. 위의 계산 결과를 -
노드의 왼쪽 자식 노드로 지정합니다.
5. 22 - 1
를 계산합니다.
6. 끝!
이걸 또 코드로 표현해보자면..
int CalculateExpTree(BTreeNode* root) {
int op1, op2;
if (root == NULL) return 0;
if (root->left_child != NULL && root->right_child != NULL)
return root->item; // 최종 계산 결과를 반환합니다.
op1 = CalculateExpTree(root->left_child);
op2 = CalculateExpTree(root->right_child);
switch (root->item) {
case '+': return op1 + op2;
case '-': return op1 - op2;
case '*': return op1 * op2;
case '/': return op1 / op2;
}
return 0;
}
아까 작성한 트리를 탐색하는 기본 원리인 재귀적 방법을 활용하면 됩니다.