C의 이진 트리: 완전한 초보자 가이드

마지막 업데이트 : 14 1월 2026
  • 노드당 최대 두 개의 자식을 가질 수 있는 계층 구조이며, 루트, 리프 및 레벨을 포함합니다.
  • 장점: 배열에 비해 효율적인 검색 및 삽입, 계층적 표현, 동적 유연성을 제공합니다.
  • 주요 작업: 데이터 정렬 및 관리를 위한 순회(입력, 사전, 사후), 검색, 삽입 및 삭제.
C의 이진 트리

C에서 이진 트리에 대한 포괄적인 가이드에 오신 것을 환영합니다. 이 글에서는 이진 트리의 기본과 C 프로그래밍 언어로 이진 트리를 구현하는 방법을 살펴보겠습니다. 프로그래밍 초보자이거나 C 기술을 향상시키고 싶다면 이 가이드가 적합합니다.

이진 트리는 컴퓨터 과학의 기본 데이터 구조 이며 다양한 응용 분야에서 사용됩니다. 이진 트리의 작동 원리와 구현 방법을 이해하면 복잡한 문제를 더욱 효율적이고 우아하게 해결할 수 있습니다.

이 글에서는 이진 트리의 구조, 노드 삽입 및 삭제, 순회, 요소 검색 등 이진 트리의 기본 사항을 살펴보겠습니다. 또한 C 프로그래밍 언어 로 작성된 실용적인 예제를 통해 이러한 개념이 실제 어떻게 적용되는지 보여드리겠습니다.

시작하겠습니다!

이진 트리란 무엇인가요?

이진 트리는 상호 연결된 노드로 구성된 계층적 데이터 구조입니다. 각 노드는 최대 두 개의 자식 노드를 가질 수 있습니다. 하나는 왼쪽에, 다른 하나는 오른쪽에 있습니다. 이러한 두 개의 분기 구조는 이진 트리를 다른 데이터 구조와 구별하는 특징입니다.

이진 트리에서는 첫 번째 노드를 루트 노드라고 합니다. 자식 노드를 자식 노드라고 하며, 자식이 없는 노드를 리프 노드라고 합니다. 같은 수준에 있는 노드를 형제 노드라고 합니다.

이진 트리의 이점

이진 트리는 효율적인 데이터 저장 및 검색 측면에서 여러 가지 이점을 제공합니다. 주요 이점은 다음과 같습니다.

  1. 효율적인 검색이진 트리를 사용하면 연결 목록 등의 다른 데이터 구조보다 런타임에 요소를 더 빠르게 검색할 수 있습니다. 이는 트리의 계층적 구조와 데이터 세트를 빠르게 분할하는 기능 덕분입니다.
  2. 유연한 삽입 및 제거이진 트리는 노드 삽입 및 삭제 작업에 매우 적응성이 뛰어납니다. 배열과 같은 정적 데이터 구조와 달리 이진 트리는 동적으로 성장하고 구조를 변경할 수 있습니다.
  3. 계층적 관계의 표현이진 트리는 특히 요소 간의 계층적 관계를 나타내는 데 유용합니다. 예를 들어, 파일 디렉토리 구조에서 각 디렉토리는 트리의 노드로 표현될 수 있으며, 하위 디렉토리와 파일은 자식 노드로 표현될 수 있습니다.

이진 트리의 구조

C에서 이진 트리를 구현하기 전에 이진 트리의 기본 구조를 이해하는 것이 중요합니다. 이진 트리의 각 노드는 값을 포함하고, 왼쪽과 오른쪽 자식 노드가 있는 경우 이에 대한 참조도 포함합니다.

다음 표는 이진 트리의 노드 구조를 보여줍니다.

바이너리 노드
용기
왼쪽 노드
오른쪽 노드

각 노드는 정수, 문자 또는 더 복잡한 구조 등 모든 유형의 데이터를 저장할 수 있습니다. 루트 노드는 트리의 시작점이며, 여기에서 다른 모든 노드에 접근할 수 있습니다.

C로 이진 트리 구현하기

이제 이진 트리에 대한 기본적인 이해를 갖게 되었으니, C 프로그래밍 언어 로 이진 트리를 구현해 볼 차례입니다 . 다음으로 C 언어에서 이진 트리 구조를 선언하고 사용하는 방법을 살펴보겠습니다.

이진 트리 구조 선언하기

C에서는 구조체와 포인터를 사용하여 이진 트리의 구조를 선언할 수 있습니다. 구조의 기본 선언은 다음과 같습니다.

struct NodoArbol {
    int valor;
    struct NodoArbol* izquierdo;
    struct NodoArbol* derecho;
};

이 구조에서는, valor 노드에 저장된 값을 나타내며, izquierdo y derecho 각각 왼쪽과 오른쪽 자식 노드를 가리키는 포인터입니다.

  Google의 Quantum Echoes 알고리즘 작동 방식

새로운 노드 생성

이진 트리에 새로운 노드를 생성하려면 노드에 대한 메모리를 할당하고 값을 설정해야 합니다. 다음은 새로운 노드를 생성하는 C 함수입니다.

struct NodoArbol* crearNodo(int valor) {
    struct NodoArbol* nodo = (struct NodoArbol*)malloc(sizeof(struct NodoArbol));
    nodo->valor = valor;
    nodo->izquierdo = NULL;
    nodo->derecho = NULL;
    return nodo;
}

함수 malloc 노드에 동적 메모리를 할당하는 데 사용됩니다. 그런 다음 노드 값을 설정하고 생성된 노드를 반환합니다.

노드 삽입

노드 삽입은 이진 트리의 기본적인 과정입니다. 노드 값에 따라 올바른 위치에 트리에 새로운 요소를 추가할 수 있습니다. 아래는 이진 트리에 노드를 삽입하는 C 함수입니다.

struct NodoArbol* insertarNodo(struct NodoArbol* raiz, int valor) {
    if (raiz == NULL) {
        return crearNodo(valor);
    }

    if (valor < raiz->valor) {
        raiz->izquierdo = insertarNodo(raiz->izquierdo, valor);
    } else if (valor > raiz->valor) {
        raiz->derecho = insertarNodo(raiz->derecho, valor);
    }

    return raiz;
}

이 함수는 트리의 루트에 대한 포인터와 삽입할 노드의 값을 받습니다. 루트가 null인 경우, 트리가 비어 있음을 의미하며 루트에 새 노드를 만듭니다. 그렇지 않으면, 노드의 값을 루트의 값과 비교하여 노드를 왼쪽이나 오른쪽에 삽입할지 결정합니다.

노드 삭제

이진 트리에서 노드를 삭제하는 것은 조금 더 복잡할 수 있습니다. 이는 삭제할 노드에 자식 노드가 있는지 없는지 등 여러 가지 경우에 따라 달라집니다. 아래는 이진 트리에서 노드를 삭제하는 C 함수입니다.

struct NodoArbol* eliminarNodo(struct NodoArbol* raiz, int valor) {
    if (raiz == NULL) {
        return raiz;
    }

    if (valor < raiz->valor) {
        raiz->izquierdo = eliminarNodo(raiz->izquierdo, valor);
    } else if (valor > raiz->valor) {
        raiz->derecho = eliminarNodo(raiz->derecho, valor);
    } else {
        if (raiz->izquierdo == NULL) {
            struct NodoArbol* temp = raiz->derecho;
            free(raiz);
            return temp;
        } else if (raiz->derecho == NULL) {
            struct NodoArbol* temp = raiz->izquierdo;
            free(raiz);
            return temp;
        }

        struct NodoArbol* sucesor = encontrarSucesor(raiz->derecho);
        raiz->valor = sucesor->valor;
        raiz->derecho = eliminarNodo(raiz->derecho, sucesor->valor);
    }

    return raiz;
}

이 함수에서는 노드의 값이 현재 루트의 값보다 작은지, 큰지, 같은지 확인합니다. 사례에 따라 다음과 같은 조치를 취합니다.

  • 값이 더 작으면 트리의 왼쪽으로 이동합니다.
  • 값이 더 크면 트리의 오른쪽으로 이동합니다.
  • 값이 같으면 노드의 가장 가까운 후속 노드(오른쪽 서브 트리의 가장 작은 노드)를 찾아 현재 노드로 대체합니다. 그런 다음 오른쪽 서브 트리에서 후속자를 제거합니다.

이진 트리에서의 순회

순회는 이진 트리의 모든 노드를 특정 순서로 방문할 수 있는 연산입니다. 일반적인 투어 유형은 세 가지가 있습니다.

중위 순회 : 왼쪽 서브트리를 먼저 방문하고, 현재 노드를 방문한 다음, 오른쪽 서브트리를 방문합니다. 다음은 이진 트리의 중위 순회를 수행하는 C 함수입니다.

void inOrden(struct NodoArbol* raiz) {
    if (raiz != NULL) {
        inOrden(raiz->izquierdo);
        printf("%d ", raiz->valor);
        inOrden(raiz->derecho);
    }
}

전위 순회 : 현재 노드를 먼저 방문하고, 그 다음 왼쪽 서브트리를 방문하고, 마지막으로 오른쪽 서브트리를 방문합니다. 다음은 이진 트리의 전위 순회를 수행하는 C 함수입니다.

void preOrden(struct NodoArbol* raiz) {
    if (raiz != NULL) {
        printf("%d ", raiz->valor);
        preOrden(raiz->izquierdo);
        preOrden(raiz->derecho);
    }
}

후위 순회 : 왼쪽 서브트리를 먼저 방문하고, 그 다음 오른쪽 서브트리를 방문한 후, 마지막으로 현재 노드를 방문합니다. 다음은 이진 트리의 후위 순회를 수행하는 C 함수입니다.

void postOrden(struct NodoArbol* raiz) {
    if (raiz != NULL) {
        postOrden(raiz->izquierdo);
        postOrden(raiz->derecho);
        printf("%d ", raiz->valor);
    }
}

요소 검색

이진 트리에서 요소를 검색하면 데이터 구조 내에서 특정 값을 빠르게 찾을 수 있습니다. 다음은 이진 트리에서 요소를 검색하는 C 함수입니다.

struct NodoArbol* buscarElemento(struct NodoArbol* raiz, int valor) {
    if (raiz == NULL || raiz->valor == valor) {
        return raiz;
    }

    if (valor < raiz->valor) {
        return buscarElemento(raiz->izquierdo, valor);
    } else {
        return buscarElemento(raiz->derecho, valor);
    }
}

이 함수는 이진 트리에서 재귀적 검색을 수행합니다. 현재 노드의 값이 검색된 값과 같으면 노드가 반환됩니다. 그렇지 않으면 값을 기준으로 왼쪽 또는 오른쪽 서브 트리를 검색하고, 값을 찾거나 널 노드에 도달할 때까지 이 과정을 반복합니다.

  Twofish: 강력한 암호화 알고리즘에 대한 모든 것

C로 이진 트리를 구현하는 예

이제 이진 트리의 기본과 C로 구현하는 방법을 살펴보았으니, 몇 가지 실제 예를 살펴보겠습니다.

예제 1: 이진 트리 생성

다음 값을 갖는 이진 트리를 만들고 싶다고 가정합니다: 10, 5, 15, 3, 7, 13, 18. C에서 이를 수행하는 방법은 다음과 같습니다:

int main() {
    struct NodoArbol* raiz = NULL;

    raiz = insertarNodo(raiz, 10);
    raiz = insertarNodo(raiz, 5);
    raiz = insertarNodo(raiz, 15);
    raiz = insertarNodo(raiz, 3);
    raiz = insertarNodo(raiz, 7);
    raiz = insertarNodo(raiz, 13);
    raiz = insertarNodo(raiz, 18);

    return 0;
}

이 예제에서 우리는 트리의 루트에 대한 포인터를 생성한 다음 함수를 사용합니다. insertarNodo 트리에 값을 추가합니다.

예제 2: 이진 트리의 순회

이진 트리의 값을 순서대로 출력하려면 다음 함수를 호출할 수 있습니다. inOrden 다음과 같이 :

int main() {
    // Crear el árbol binario

    printf("Recorrido en orden: ");
    inOrden(raiz);
    printf("\n");

    return 0;
}

이 예제는 트리의 값을 오름차순으로 인쇄합니다.

Preguntas frecuentes

1. 이진 트리와 이진 검색 트리의 차이점은 무엇입니까?

이진 탐색 트리(BST)는 값이 작을수록 왼쪽에, 값이 클수록 오른쪽에 배치되는 특수한 유형의 이진 트리입니다. 이를 통해 일반 이진 트리에 비해 요소를 더 효율적으로 검색할 수 있습니다.

2. 이진 트리에서 중복된 값을 갖는 노드가 있을 수 있나요?

네, 이진 트리에서는 중복된 값을 갖는 노드가 있을 수 있습니다. 그러나 이진 트리의 구현과 특정 규칙에 따라 중복 노드를 처리하는 방법이 달라질 수 있습니다. 일부 구현에서는 중복을 허용하고 이를 임의의 순서로 저장할 수 있지만, 다른 구현에서는 중복 값을 특별히 처리하거나 삭제해야 할 수 있습니다.

3. 이진 트리에서 특정 노드를 제거하려면 어떻게 해야 하나요?

이진 트리에서 특정 노드를 제거하려면 다음 단계를 따라야 합니다.

  1. 트리 검색을 사용하여 삭제하려는 노드를 찾으세요.
  2. 제거의 다양한 사례를 고려해 보겠습니다.
    • 노드에 자식이 없으면 간단히 해당 노드를 삭제하고 메모리를 해제하면 됩니다.
    • 노드에 자식이 하나만 있는 경우 해당 노드를 자식 노드로 바꿀 수 있습니다.
    • 노드에 두 개의 자식이 있는 경우 가장 가까운 후속 노드(오른쪽 서브 트리의 가장 작은 노드)를 찾고 삭제할 노드의 값을 후속 노드의 값으로 대체해야 합니다. 그런 다음 나무에서 후속 개체를 제거합니다.
  3. 올바른 트리 구조를 유지하기 위해 필요에 따라 링크와 포인터를 조정합니다.
  구조화된 프로그래밍: 기본 개념 및 원칙

4. 완전 이진 트리란 무엇입니까?

완전 이진 트리는 모든 레벨(마지막 레벨 제외)이 완전히 채워지고 마지막 레벨의 노드가 가능한 한 왼쪽에 위치하는 특수한 유형의 이진 트리입니다. 이는 모든 노드가 두 개의 자식을 갖는다는 것을 의미하는데, 마지막 레벨의 노드는 자식이 하나이거나 없을 수 있습니다.

5. 이진 트리의 높이는 얼마입니까?

이진 트리의 높이는 루트에서 리프까지의 가장 긴 경로의 길이입니다. 즉, 트리의 루트와 모든 리프 사이의 최대 간선 개수입니다. 높이는 레벨 수로 측정되므로 노드가 하나만 있는 트리의 높이는 0이고, 빈 트리의 높이는 없습니다.

6. 프로그램에서 이진 트리를 사용해야 하는 경우는 언제인가요?

이진 트리는 다양한 상황에서 유용합니다. 이진 트리를 사용할 수 있는 일반적인 경우는 다음과 같습니다.

  • 효율적인 요소 조회: 데이터 구조에서 요소를 빠르게 조회해야 하는 경우 이진 트리가 데이터에 효율적으로 액세스할 수 있도록 해줍니다.
  • 계층적 관계 표현: 이진 트리는 디렉토리 구조와 같은 계층적 관계를 표현하는 데 이상적입니다. 파일 시스템.
  • 데이터 정렬: 이진 검색 트리를 사용하면 효율적으로 데이터를 정렬하고 대수적 시간 안에 검색, 삽입, 삭제를 수행할 수 있습니다.

프로그램에서 이진 트리를 사용하기로 결정하기 전에 요구 사항을 평가하고 이진 트리에서 수행하는 연산의 복잡성을 고려해야 합니다.

결론

이 포괄적인 가이드에서는 C로 작성된 이진 트리의 기본 개념을 살펴보았습니다. 이진 트리의 구조, 노드를 삽입하고 제거하는 방법, 순회를 수행하는 방법, 이진 트리에서 요소를 검색하는 방법에 대해 알아보았습니다.

이 가이드가 이진 트리에 대한 확실한 이해와 C에서 이진 트리를 구현하는 방법을 제공했기를 바랍니다. 이진 트리는 프로그래밍에서 다양한 문제를 해결하는 데 도움이 되는 다재다능하고 강력한 데이터 구조입니다.

제공된 예제를 연습하고 실험하여 C에서 이진 트리에 대한 이해를 강화하세요. 소프트웨어 학습 및 개발 여정에서 행운을 빕니다!