본문 바로가기

자료구조

Tree

Tree

트리 자료구조

트리는 노드 들이 나무가지처럼 연결된 비선형적 자료구조이다.

선형적 자료구조는 하나의 자료 뒤에 하나의 자료가 존재한다.

자료들간의 앞과 뒤 관계가 1대 1인 경우를 선형적이라고 얘기한다.

비선형은 그렇지 않은 경우라고 생각하면 편할 것 같다.

트리의 이미지를 보면, 한 눈에 보기에도 비선형적 자료구조라는 것을 알 수 있다.

마찬가지로 하나의 트리가 또 다른 트리를 포함할 수 있으며, 이는 재귀적 자료구조라고 볼 수 있다.

트리의 용어

트리 구조에서 주로 사용하는 몇 가지 용어가 존재한다.

자주 쓰는 용어들만 정리하자면 다음과 같다.


Node: 트리를 구성하는 기본 요소

Edge: Node와 Node간의 연결 선

Root Node: 트리 구조에서 부모가 없는 최상위 Node

Parent Node: Child를 가지는 Node

Child Node: Parent Node의 하위 Node

Sibling Node: 같은 Parent를 공유하는 Node

External Node == Terminal Node == Leaf Node: Child가 없는 Node

Internal Node == Non-Terminal Node == Branch Node: Child를 하나 이상 가지는 Node

트리의 특징

다음은 트리의 특징을 정리한 것이며, 이에 위배될 경우 트리 자료구조라고 할 수 없다.

  • 하나의 루트노드와 0개 이상의 하위 노드로 구성
  • 데이터를 순차적으로 저장하지 않는 비선형적 자료구조
  • 트리내에 또 다른 트리가 있는 재귀적 자료구조
  • 무방향 그래프 구조
  • 자식 노드는 하나의 부모노드만을 가진다
  • 노드가 N개인 트리는 N-1개의 간선을 가진다

이진트리 구현

# header

typedef struct BinTreeNodeType
{
    char data;
    int visited;
    struct BinTreeNodeType    *pLeftChild;
    struct BinTreeNodeType    *pRightChild;
} BinTreeNode;

typedef struct BinTreeType
{
    struct BinTreeNodeType* pRootNode;
} BinTree;
#include "./bintree.h"

BinTree        *makeBinTree(BinTreeNode rootNode)
{
    BinTree        *newTree = calloc(1, sizeof(BinTree));
    BinTreeNode    *root = calloc(1, sizeof(BinTreeNode));

    root->data = rootNode.data;
    root->visited = 0;
    newTree->pRootNode = root;
    return (newTree);
}

BinTreeNode    *getRootNodeBT(BinTree *pBinTree)
{
    if (!pBinTree)
        return  (NULL);
    printf("root node data = %c\n", pBinTree->pRootNode->data);
    return (pBinTree->pRootNode);
}

// 부모노드에 자식 노드를 왼쪽에 넣어주고 자식노드를 리턴
BinTreeNode    *insertLeftChildNodeBT(BinTreeNode *pParentNode, BinTreeNode element)
{
    if (!pParentNode)
        return (NULL);
    BinTreeNode    *newNode = calloc(1, sizeof(BinTreeNode));
    newNode->data = element.data;
    newNode->visited = 0;
    pParentNode->pLeftChild = newNode;
    return (newNode);
}

// 부모노드에 자식 노드를 오른쪽에 넣어주고 자식노드를 리턴
BinTreeNode    *insertRightChildNodeBT(BinTreeNode *pParentNode, BinTreeNode element)
{
    if (!pParentNode)
        return (NULL);
    BinTreeNode    *newNode = calloc(1, sizeof(BinTreeNode));
    newNode->data = element.data;
    newNode->visited = 0;
    pParentNode->pRightChild = newNode;
    return (newNode);
}

// 노드의 왼쪽 자식노드를 리턴
BinTreeNode    *getLeftChildNodeBT(BinTreeNode *pNode)
{
    if (!(pNode->pLeftChild))
        return (NULL);
    return (pNode->pLeftChild);
}

// 노드의 오른쪽 자식노드를 리턴
BinTreeNode    *getRightChildNodeBT(BinTreeNode* pNode)
{
    if (!(pNode->pRightChild))
        return (NULL);
    return (pNode->pRightChild);
}

// 노드 하나를 삭제 
void    deleteBinTreeNode(BinTreeNode* pNode)
{
    pNode->pLeftChild = NULL;
    pNode->pRightChild = NULL;
    free(pNode);
}

// 트리 전체를 삭제
void    deleteBinTree(BinTree *pBinTree)
{
    if (!pBinTree)
        return ;
    free_leafNode(pBinTree->pRootNode);
    free(pBinTree);
}

void    free_leafNode(BinTreeNode *parentNode)
{
    if (parentNode->pLeftChild)
        free_leafNode(parentNode->pLeftChild);
    if (parentNode->pRightChild)
        free_leafNode(parentNode->pRightChild);
    free(parentNode);
}

'자료구조' 카테고리의 다른 글

Heap  (0) 2022.05.23
Recursive  (0) 2022.05.23
Queue  (0) 2022.05.23
Stack  (0) 2022.05.23
Array List, Linked List  (0) 2022.05.23