계층적인 관계를 나타내는 데 편리한 것이 트리로써,
트리의 구성 요소에 해당 하는 것을 노드라 칭한다
트리의 개념
Root Node : 부모가 없는 노드 (원조격인 노드)
leaf or Terminal Node (단일 노드) : 자식이 없는 노드
Internal Node : 리프 노드를 제외한 모든 노드
부모 노드 : B, G 노드의 부모 노드는 F이다.
자식 노드 : F 노드의 자식 노드는 B, G이다.
선조 노드 : 주어진 노드의 상위에 있는 노드들, B, F는 D의 선조 노드이다.
후손 노드 : 역으로 어떤 노드의 하위에 있는 노드들, F의 후손은 그 아래 모든 노드들이다.
형제 노드 : 같은 부모를 두고 있는 노드들, B, G 노드는 형제 노드이다.
트리의 차수 : 자식 노드의 개수
트리의 레벨 : 루트노드를 레벨 0으로 하고 아래로 내려오면서 증가, E 는 레벨 3이다.
트리의 높이 : 트리내의 최대 레벨과 일치
1
|
트리의 높이 = 1 + Max(왼쪽 하위트리의 높이, 오른쪽 하위트리의 높이)
|
cs |
이진 트리
최대 차수가 2개인 트리
아무런 노드가 없거나 가운데 노드를 중심으로 좌우로 나누어지되, 좌우 하위트리 모두 이진트리
포화 이진트리
- 높이 h인 이진트리에서 모든 리프노드가 레벨 h에 있는 트리
완전 이진트리
- 높이 h인 완전 이진트리는 레벨 (h-1)까지는 포화 이진트리이고, 마지막 레벨 h에서 왼쪽부터 차례대로 리프노드를 채운 트리
배열을 이용한 이진트리 구현
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
31
32
33
34
35
36
37
|
#ifndef _BIN_TREE_AL_
#define _BIN_TREE_AL_
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 16
typedef struct TreeNodeAL
{
char data;
} TreeNodeAL;
typedef struct TreeAL
{
int count;
TreeNodeAL TreeArray[MAXSIZE];
} TreeAL;
void makeRoot(TreeAL *Lptr, char data);
void InsertLeftChildAL(TreeAL *Lptr, int position, char data);
void InsertRightChildAL(TreeAL *Lptr, int position, char data);
char getLeftChildAL(TreeAL *Lptr, int position);
char getRightChildAL(TreeAL *Lptr, int position);
void display(TreeAL *Tree);
void deleteTreeAL(TreeAL *Tree);
#endif
#ifndef _COMMON_TREE_DEF_
#define _COMMON_TREE_DEF_
#define TRUE 1
#define FALSE 0
#endif
|
cs |
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
#include "BinTree_AL.h"
void makeRoot(TreeAL *Lptr, char data){
Lptr->TreeArray[1].data = data;
Lptr->count++;
}
void InsertLeftChildAL(TreeAL *Lptr, int position, char data){
if (position < 1 || position * 2 >= MAXSIZE)
{
printf("Error : Out of the range");
return ;
}
else if (Lptr->TreeArray[position * 2].data != 0)
{
printf("Error : LeftChild is FULL");
return ;
}
Lptr->TreeArray[position * 2].data = data;
Lptr->count++;
}
void InsertRightChildAL(TreeAL *Lptr, int position, char data){
if (position < 1 || (position * 2) + 1 >= MAXSIZE)
{
printf("Error : Out of the range");
return ;
}
else if (Lptr->TreeArray[(position * 2) + 1].data != 0)
{
printf("Error : RightChild is FULL");
return ;
}
Lptr->TreeArray[(position * 2) + 1].data = data;
Lptr->count++;
}
char getLeftChildAL(TreeAL *Lptr, int position)
{
char ret = Lptr->TreeArray[position * 2].data;
if (ret == 0)
{
printf("Error : LeftChild is Empty");
return 0;
}
return ret;
}
char getRightChildAL(TreeAL *Lptr, int position)
{
char ret = Lptr->TreeArray[(position * 2) + 1].data;
if (ret == 0)
{
printf("Error : RightChild is Empty");
return 0;
}
return ret;
}
void display(TreeAL *Tree) {
for (int i = 1; i <= Tree->count; i++)
printf("%c ", Tree->TreeArray[i].data);
printf("\n");
}
void deleteTreeAL(TreeAL *Tree){
for (int i = Tree->count; i > 0; i--)
Tree->TreeArray[i].data = 0;
}
|
cs |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#include "BinTree_AL.h"
int main(){
TreeAL *L = (TreeAL*)malloc(sizeof(TreeAL));
makeRoot(L, 'A');
InsertLeftChildAL(L, 1, 'B');
InsertRightChildAL(L, 1, 'C');
InsertLeftChildAL(L, 2, 'D');
InsertRightChildAL(L, 2, 'E');
InsertLeftChildAL(L, 4, 'H');
InsertRightChildAL(L, 4, 'I');
InsertLeftChildAL(L, 5, 'J');
InsertRightChildAL(L, 5, 'K');
InsertLeftChildAL(L, 3, 'F');
InsertRightChildAL(L, 3, 'G');
InsertLeftChildAL(L, 6, 'L');
InsertRightChildAL(L, 6, 'M');
display(L);
}
|
cs |
포인터를 이용한 이진 트리구현
BinTree.h
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
31
32
33
34
35
36
37
38
|
#ifndef _BIN_TREE_
#define _BIN_TREE_
#include <stdio.h>
#include <stdlib.h>
typedef struct BinTreeNodeType
{
char data;
int visited;
struct BinTreeNodeType* pLeftChild;
struct BinTreeNodeType* pRightChild;
} BinTreeNode;
typedef struct BinTreeType
{
struct BinTreeNodeType* pRootNode;
} BinTree;
BinTree* makeBinTree(BinTreeNode rootNode);
BinTreeNode* getRootNodeBT(BinTree* pBinTree);
BinTreeNode* insertLeftChildNodeBT(BinTreeNode* pParentNode, BinTreeNode element);
BinTreeNode* insertRightChildNodeBT(BinTreeNode* pParentNode, BinTreeNode element);
BinTreeNode* getLeftChildNodeBT(BinTreeNode* pNode);
BinTreeNode* getRightChildNodeBT(BinTreeNode* pNode);
void deleteBinTree(BinTree* pBinTree);
void deleteBinTreeNode(BinTreeNode* pNode);
#endif
#ifndef _COMMON_TREE_DEF_
#define _COMMON_TREE_DEF_
#define TRUE 1
#define FALSE 0
#endif
|
cs |
BinTree.c
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
#include "BinTree.h"
BinTree* makeBinTree(BinTreeNode rootNode)
{
BinTree* pReturn = NULL;
pReturn = (BinTree*)malloc(sizeof(BinTree));
if (pReturn != NULL)
{
pReturn->pRootNode = (BinTreeNode*)malloc(sizeof(BinTreeNode));
if (pReturn->pRootNode != NULL)
{
*pReturn->pRootNode = rootNode;
pReturn->pRootNode->pLeftChild = NULL;
pReturn->pRootNode->pRightChild = NULL;
}
else
printf("Memory Allocation Failure\n");
}
else
printf("Memory Allocation Failure\n");
return (pReturn);
}
BinTreeNode* getRootNodeBT(BinTree* pBinTree)
{
BinTreeNode* pReturn = NULL;
if (pBinTree != NULL)
{
pReturn = pBinTree->pRootNode;
}
return (pReturn);
}
BinTreeNode* insertLeftChildNodeBT(BinTreeNode* pParentNode, BinTreeNode element)
{
BinTreeNode* pReturn = NULL;
if (pParentNode != NULL)
{
if (pParentNode->pLeftChild == NULL)
{
pParentNode->pLeftChild = (BinTreeNode*)malloc(sizeof(BinTreeNode));
*pParentNode->pLeftChild = element;
pParentNode->pLeftChild->pLeftChild = NULL;
pParentNode->pLeftChild->pRightChild = NULL;
pReturn = pParentNode->pLeftChild;
}
else
printf("Already Node is Existing\n");
}
return (pReturn);
}
BinTreeNode* insertRightChildNodeBT(BinTreeNode* pParentNode, BinTreeNode element)
{
BinTreeNode* pReturn = NULL;
if (pParentNode != NULL)
{
if (pParentNode->pRightChild == NULL)
{
pParentNode->pRightChild = (BinTreeNode*)malloc(sizeof(BinTreeNode));
*pParentNode->pRightChild = element;
pParentNode->pRightChild->pLeftChild = NULL;
pParentNode->pRightChild->pRightChild = NULL;
pReturn = pParentNode->pRightChild;
}
else
printf("Already Node is Existing\n");
}
return (pReturn);
}
BinTreeNode* getLeftChildNodeBT(BinTreeNode* pNode)
{
BinTreeNode* pReturn = NULL;
if (pNode != NULL)
{
pReturn = pNode->pLeftChild;
}
return (pReturn);
}
BinTreeNode* getRightChildNodeBT(BinTreeNode* pNode)
{
BinTreeNode* pReturn = NULL;
if (pNode != NULL)
{
pReturn = pNode->pRightChild;
}
return (pReturn);
}
void deleteBinTree(BinTree* pBinTree)
{
deleteBinTreeNode(pBinTree->pRootNode);
free(pBinTree);
}
void deleteBinTreeNode(BinTreeNode* pNode)
{
if (pNode != NULL)
{
deleteBinTreeNode(pNode->pLeftChild);
deleteBinTreeNode(pNode->pRightChild);
free(pNode);
}
}
|
cs |
BinTreeTraversal.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#include "BinTree.h"
void PreOrderBinTree(BinTree *pBinTree);
void PreOrderBinTreeNode(BinTreeNode* pRootNode);
void InOrderBinTree(BinTree *pBinTree);
void InOrderBinTreeNode(BinTreeNode* pRootNode);
void PostOrderBinTree(BinTree *pBinTree);
void PostOrderBinTreeNode(BinTreeNode* pRootNode);
void displayVisited(BinTree *pBinTree);
void displayVisitedNode(BinTreeNode* pRootNode);
void clearVisited(BinTree* pBinTree);
void clearVisitedNode(BinTreeNode* pRootNode);
|
cs |
BinTreeTraversal.c
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
#include "BinTree.h"
#include "BinTreeTraversal.h"
void PreOrderBinTree(BinTree *pBinTree)
{
if (pBinTree != NULL)
{
PreOrderBinTreeNode(pBinTree->pRootNode);
}
}
void PreOrderBinTreeNode(BinTreeNode* pRootNode)
{
if (pRootNode != NULL)
{
pRootNode->visited = TRUE;
printf("%c -> ", pRootNode->data);
PreOrderBinTreeNode(pRootNode->pLeftChild);
PreOrderBinTreeNode(pRootNode->pRightChild);
}
}
void InOrderBinTree(BinTree *pBinTree)
{
if (pBinTree != NULL)
{
InOrderBinTreeNode(pBinTree->pRootNode);
}
}
void InOrderBinTreeNode(BinTreeNode* pRootNode)
{
if (pRootNode == NULL)
return ;
InOrderBinTreeNode(pRootNode->pLeftChild);
pRootNode->visited = TRUE;
printf("%c -> ", pRootNode->data);
InOrderBinTreeNode(pRootNode->pRightChild);
}
void PostOrderBinTree(BinTree *pBinTree)
{
if (pBinTree != NULL)
PostOrderBinTreeNode(pBinTree->pRootNode);
}
void PostOrderBinTreeNode(BinTreeNode* pRootNode)
{
if (pRootNode == NULL)
return ;
PostOrderBinTreeNode(pRootNode->pLeftChild);
PostOrderBinTreeNode(pRootNode->pRightChild);
pRootNode->visited = TRUE;
printf("%c -> ", pRootNode->data);
}
void displayVisited(BinTree *pBinTree)
{
if (pBinTree != NULL)
displayVisitedNode(pBinTree->pRootNode);
}
void displayVisitedNode(BinTreeNode* pRootNode)
{
if (pRootNode != NULL)
{
printf("%c Node Visited : %d\n", pRootNode->data, pRootNode->visited);
displayVisitedNode(pRootNode->pLeftChild);
displayVisitedNode(pRootNode->pRightChild);
}
}
void clearVisited(BinTree *pBinTree)
{
if (pBinTree != NULL)
clearVisitedNode(pBinTree->pRootNode);
}
void clearVisitedNode(BinTreeNode* pRootNode)
{
if (pRootNode != NULL)
{
pRootNode->visited = FALSE;
clearVisitedNode(pRootNode->pLeftChild);
clearVisitedNode(pRootNode->pRightChild);
}
}
|
cs |
main.c
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
#include "BinTree.h"
#include "BinTreeTraversal.h"
int main()
{
BinTree* pBinTree = NULL;
BinTreeNode* pNode1 = NULL;
BinTreeNode* pNode2 = NULL;
BinTreeNode* pNode3 = NULL;
BinTreeNode* pNode4 = NULL;
BinTreeNode* pNode5 = NULL;
BinTreeNode* pNode6 = NULL;
BinTreeNode* pNode7 = NULL;
BinTreeNode node = { 0, };
node.data = 'A';
pBinTree = makeBinTree(node);
if (pBinTree != NULL)
{
pNode1 = getRootNodeBT(pBinTree);
node.data = 'B';
pNode2 = insertLeftChildNodeBT(pNode1, node);
node.data = 'C';
pNode3 = insertRightChildNodeBT(pNode1, node);
node.data = 'D';
pNode4 = insertLeftChildNodeBT(pNode2, node);
node.data = 'E';
pNode5 = insertRightChildNodeBT(pNode2, node);
node.data = 'F';
pNode6 = insertLeftChildNodeBT(pNode3, node);
node.data ='G';
pNode7 = insertRightChildNodeBT(pNode3, node);
}
if (pBinTree != NULL)
{
printf("PreOrder Traversal\n");
PreOrderBinTree(pBinTree);
printf("\n");
displayVisited(pBinTree);
printf("\n\n");
clearVisited(pBinTree);
printf("InOrder Traversal\n");
InOrderBinTree(pBinTree);
printf("\n\n");
clearVisited(pBinTree);
printf("PostOrder Traversal\n");
PostOrderBinTree(pBinTree);
printf("\n");
deleteBinTree(pBinTree);
}
return (0);
}
|
cs |
이진 트리의 순회
V : 부모 노드 L : 왼쪽 자식 노드 R : 오른쪽 자식 노드
Preorder Travelsal(전위 순회)
- 방문 순서 : V - L - R
Inoreder Travelsal(중위 순회)
- 방문 순서 : L - V - R
Postorder Travelsal(후위 순회)
- 방문 순서 : L - R - V
Level-order Travelsal(레벨 순서 순회)
- 모든 노드를 낮은 레벨부터 차례대로 순회, 너비 우선 순회라고도 칭한다
- 위의 그림의 트리라면,
- 레벨 순서 순회: F, B, G, A, D, I, C, E, H
'자료구조와 알고리즘 > 자료구조' 카테고리의 다른 글
[C언어] Tree / BST 이진 탐색트리 구현 - 3편 (3) | 2021.09.12 |
---|---|
[C언어] Tree / Heap 힙 구현 - 2편 (1) | 2021.09.11 |
[C언어] Queue (큐) (2) | 2021.09.04 |
[C언어] Stack (스택) (2) | 2021.09.02 |
[C언어] Array & Linked lists (배열 & 연결 리스트) (0) | 2021.08.13 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!