[Algorithm] Generic Tree
Tree 기본 구조 및 용어

Tree 구조의 특징은 어떤 데이터를 찾고자 할 때 좀 더 빠른 시간 내에 찾을 수 있는 장점을 가진다. 구조는 아래 그림과 같이 root를 기점으로 좌 우 노드와 연결되어 있다.
Tree에서 사용되는 용어 몇 가지가 있는데 다음과 같다.
Root: 최상단 노드
Leaf: 최하단 노드
Level: Root 노드는 0이며, 아래로 갈 수록 level이 높아짐
Depth: 가장 level이 높은 leaf level을 가리키는 말
순회 (Traverse)
Tree를 순회 할 때는 순서가 중요한데, 다음과 같이 root의 순서를 기준으로 3 가지로 나뉜다.
Pre-order Traverse: root -> left -> right
In-order Traverse: left -> root -> right
Post-order Traverse: left -> right -> root
코드
Tree 구조가 위 그림과 같다고 가정한다면 아래처럼 코드를 작성 할 수 있다.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *left;
struct node *right;
} NODE;
NODE *root;
typedef enum {LEFT, RIGHT} FLAG;
void insert_data(int data, NODE *s, FLAG flag) {
NODE *temp;
temp = malloc(sizeof(NODE));
temp->data = data;
temp->left = 0;
temp->right = 0;
if(root == 0) {
root = temp;
return;
}
if(flag == LEFT) s->left = temp;
else if(flag == RIGHT) s->right = temp;
}
void pre_order(NODE *temp) {
if(temp == 0)
return;
printf("%d\n", temp->data);
pre_order(temp->left);
pre_order(temp->right);
}
void in_order(NODE *temp) {
if(temp == 0)
return;
in_order(temp->left);
printf("%d\n", temp->data);
in_order(temp->right);
}
void post_order(NODE *temp) {
if(temp == 0)
return;
post_order(temp->left);
post_order(temp->right);
printf("%d\n", temp->data);
}
int main() {
insert_data(1, root, LEFT);
insert_data(2, root, LEFT);
insert_data(3, root, RIGHT);
insert_data(4, root->left, LEFT);
insert_data(5, root->left, RIGHT);
insert_data(6, root->right, LEFT);
insert_data(7, root->right, RIGHT);
in_order(root);
in_order(root);
in_order(root);
return 0;
}
Display 함수
Tree 구조를 display하는 건 쉽지 않다. 따라서 display 함수를 tree 구조에 맞게 구현이 필요하다.
Level 1
우선 tree를 왼쪽으로 뉘인 것 처럼 display를 하는 방법이 있다. 대신 이 방법으로 하려면 우선 순회 순서를 display 용으로 변경해줘야 한다. 각 하위 노드로 넘어 갈 때마다 indent값을 증가시키면서 출력하는 방법이다.
Display Traverse: right -> root -> left
이렇게 해야 왼쪽으로 눕혔을 때 tree 모습이 나오게 된다.
void display(NODE *temp) {
static int indent = -1;
if(temp == 0)
return;
++indent;
display(temp->right);
for(int i=0; i<indent; i++)
printf("%4c",' ');
printf("%d\n", temp->data);
display(temp->left);
--indent;
}

Level 2
Tree를 눕히지 않고 우리가 보는 모습대로 출력하기 위해선 출력 전에 배열 구조에서 재배치를 한 뒤에 출력하는 방법이다. 이 방식으로 display 하기 위해선 우선 in-order traverse 로 순회하면서 동일하게 하위 노드로 갈 때마다 row를 증가시키고, 값을 쓸 때마다 column을 증가시킨다.

int (*__display(NODE *temp)) [10]{
static int row = -1;
static int col = 0;
static int array[10][10] = {0,};
if(temp == 0)
return array;
++row;
__display(temp->left);
array[row][col++] = temp->data;
__display(temp->right);
--row;
return array;
}
void display(NODE *temp) {
int (*a)[10];
a = __display(temp);
for(int i=0; i<10; i++) {
for(int j=0; j<10; j++) {
if(a[i][j])
printf("%4d", a[i][j]);
else
printf("%4c", ' ');
}
printf("\n");
}
}
shumin@mercury:~/workspace/00_Algorithm/03_Generic_Tree$ ./a.out
1
2 3
4 5 6 7
Level 3
실제 simulator처럼 매 값이 들어 올 때마다 출력이 되도록 하고자 한다. 이를 위해선 row, col, array 변수를 coller로 옮겨주고 내부 display 함수인 __display의 인자로 해당 변수의 주소를 넘겨주면서 해야한다.
int __display(NODE *temp, int (*array)[10], int *row, int *col) {
if(temp == 0)
return 0;
++*row;
__display(temp->left, array, row, col);
array[*row][(*col)++] = temp->data;
__display(temp->right, array, row, col);
--*row;
}
void display(NODE *temp) {
int row = -1;
int col = 0;
int a[10][10] = {0,};
__display(temp, a, &row, &col);
system("clear");
for(int i=0; i<10; i++) {
for(int j=0; j<10; j++) {
if(a[i][j])
printf("%4d", a[i][j]);
else
printf("%4c", ' ');
}
printf("\n");
}
getchar();
}
int main() {
insert_data(1, root, LEFT);
display(root);
insert_data(2, root, LEFT);
display(root);
insert_data(3, root, RIGHT);
display(root);
insert_data(4, root->left, LEFT);
display(root);
insert_data(5, root->left, RIGHT);
display(root);
insert_data(6, root->right, LEFT);
display(root);
insert_data(7, root->right, RIGHT);
display(root);
return 0;
}
1
2 3
4 5 6 7