23.3. 프로그램언어 C++에서의 트리 구조

프로그램언어 C++에서의 트리 구조의 기본 개념

트리 구조는 계층적인 데이터 구조로, 노드들이 부모-자식 관계로 연결된 형태를 가지는 자료구조입니다. 각 노드는 하나의 부모 노드와 여러 개의 자식 노드를 가질 수 있습니다. 트리 구조에서 맨 위에 있는 노드를 루트 노드라고 하며, 맨 아래에 있는 노드들을 리프 노드라고 합니다.

프로그램언어 C++에서 트리 구조를 구현할 때는 주로 포인터를 이용하여 노드들을 연결합니다. 각 노드는 데이터를 저장하는 변수와 부모, 자식 노드를 가리키는 포인터 변수로 구성됩니다. 아래는 간단한 이진 트리를 구현하는 예제 코드입니다.


#include <iostream>

struct Node {
    int data;
    Node* left;
    Node* right;
    
    Node(int value) : data(value), left(nullptr), right(nullptr) {}
};

int main() {
    Node* root = new Node(1);
    root->left = new Node(2);
    root->right = new Node(3);
    
    root->left->left = new Node(4);
    root->left->right = new Node(5);
    
    return 0;
}

프로그램언어 C++의 이진 트리의 표현법

이진 트리는 각 노드가 최대 두 개의 자식 노드를 가지는 트리 구조를 말합니다. C++에서 이진 트리를 표현하는 방법에는 포인터를 이용한 방법과 배열을 이용한 방법이 있습니다.

포인터를 이용한 방법:
이 방법은 각 노드를 나타내는 구조체를 선언하고, 각 노드의 왼쪽 자식과 오른쪽 자식을 가리키는 포인터를 이용하여 이진 트리를 구현합니다.


#include <iostream>

struct Node {
    int data;
    Node* left;
    Node* right;
};

int main() {
    Node* root = new Node{1, nullptr, nullptr};
    root->left = new Node{2, nullptr, nullptr};
    root->right = new Node{3, nullptr, nullptr};

    return 0;
}

배열을 이용한 방법:
이 방법은 배열을 이용하여 각 노드의 위치를 계산하여 이진 트리를 구현합니다. 일반적으로 배열을 이용한 방법은 완전 이진 트리에 적합합니다.


#include <iostream>

#define MAX_SIZE 100

int tree[MAX_SIZE];

void insert(int value, int index) {
    if (tree[index] == 0) {
        tree[index] = value;
    }
    else {
        if (value < tree[index]) {
            insert(value, 2 * index + 1);
        }
        else {
            insert(value, 2 * index + 2);
        }
    }
}

int main() {
    insert(1, 0);
    insert(2, 0);
    insert(3, 0);

    return 0;
}

프로그램언어 C++에서의 트리 탐색 알고리즘

트리 탐색 알고리즘은 트리 구조에서 원하는 노드를 찾거나 순회하는 방법을 의미합니다. 대표적인 트리 탐색 알고리즘으로는 깊이 우선 탐색(DFS)과 너비 우선 탐색(BFS)이 있습니다. C++에서는 이러한 알고리즘을 구현할 수 있습니다.

깊이 우선 탐색(DFS)
DFS는 한 노드에서 시작해 그래프의 깊이를 우선적으로 탐색하는 알고리즘입니다. 재귀 함수나 스택을 활용하여 구현할 수 있습니다. 아래는 재귀 함수를 사용한 DFS의 예제 코드입니다.


#include <iostream>
#include <vector>

using namespace std;

vector<vector<int>> adj; // 인접 리스트
vector<bool> visited;

void dfs(int node) {
    visited[node] = true;
    cout << node << " ";

    for (int next : adj[node]) {
        if (!visited[next]) {
            dfs(next);
        }
    }
}

int main() {
    int n, m;
    cin >> n >> m;

    adj.resize(n + 1);
    visited.resize(n + 1, false);

    for (int i = 0; i < m; ++i) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    dfs(1); // 1번 노드부터 DFS 시작

    return 0;
}

너비 우선 탐색(BFS)
BFS는 한 노드에서 시작해 그래프의 너비를 우선적으로 탐색하는 알고리즘입니다. 큐를 활용하여 구현할 수 있습니다. 아래는 큐를 사용한 BFS의 예제 코드입니다.


#include <iostream>
#include <queue>
#include <vector>

using namespace std;

vector<vector<int>> adj; // 인접 리스트
vector<bool> visited;

void bfs(int start) {
    queue<int> q;
    q.push(start);
    visited[start] = true;

    while (!q.empty()) {
        int cur = q.front();
        q.pop();
        cout << cur << " ";

        for (int next : adj[cur]) {
            if (!visited[next]) {
                q.push(next);
                visited[next] = true;
            }
        }
    }
}

int main() {
    int n, m;
    cin >> n >> m;

    adj.resize(n + 1);
    visited.resize(n + 1, false);

    for (int i = 0; i < m; ++i) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    bfs(1); // 1번 노드부터 BFS 시작

    return 0;
}

프로그램언어 C++에서의 트리와 그래프의 차이

트리와 그래프의 차이

트리와 그래프는 자료구조에서 중요한 개념으로, 각각의 특징과 용도가 다릅니다.

트리(Tree)

트리는 계층적인 구조를 가지며, 노드들이 부모-자식 관계로 연결된 자료구조입니다. 각 노드는 최대 하나의 부모 노드와 여러 개의 자식 노드를 가질 수 있습니다. 트리는 사이클이 없고 하나의 루트 노드를 가지며, 모든 노드는 서로 연결되어 있습니다.

그래프(Graph)

그래프는 노드와 간선으로 이루어진 자료구조로, 노드들 간의 관계를 표현합니다. 그래프는 방향성과 순환이 있는 사이클을 가질 수 있으며, 노드들 간에 임의의 관계를 가질 수 있습니다.

예제 코드


#include <iostream>
#include <vector>

using namespace std;

// 트리 예제
class TreeNode {
public:
    int val;
    vector<TreeNode*> children;
    
    TreeNode(int value) : val(value) {}
};

// 그래프 예제
class GraphNode {
public:
    int val;
    vector<GraphNode*> neighbors;
    
    GraphNode(int value) : val(value) {}
};

int main() {
    // 트리 생성
    TreeNode* root = new TreeNode(1);
    root->children.push_back(new TreeNode(2));
    root->children.push_back(new TreeNode(3));
    
    // 그래프 생성
    GraphNode* node1 = new GraphNode(1);
    GraphNode* node2 = new GraphNode(2);
    GraphNode* node3 = new GraphNode(3);
    
    node1->neighbors.push_back(node2);
    node2->neighbors.push_back(node3);
    node3->neighbors.push_back(node1);
    
    return 0;
}
    

프로그램언어 C++의 트리 구조의 활용 방법

C++에서 트리 구조를 활용하는 방법은 다양한 알고리즘 및 데이터 구조에서 중요한 역할을 합니다. 트리는 노드들이 부모-자식 관계로 이루어진 계층적인 구조를 가지며, 이를 효과적으로 활용하여 다양한 문제를 해결할 수 있습니다.

트리 구조를 사용하는 대표적인 예시로는 이진 탐색 트리(Binary Search Tree)가 있습니다. 이진 탐색 트리는 각 노드가 최대 두 개의 자식 노드를 가지며, 왼쪽 자식 노드는 현재 노드보다 작은 값을, 오른쪽 자식 노드는 현재 노드보다 큰 값을 가지도록 구성됩니다. 이를 통해 데이터를 효율적으로 탐색하고 삽입, 삭제할 수 있습니다.

아래는 C++로 이진 탐색 트리를 구현하는 간단한 예제 코드입니다.


#include <iostream>

struct Node {
    int data;
    Node* left;
    Node* right;

    Node(int value) : data(value), left(nullptr), right(nullptr) {}
};

class BinarySearchTree {
private:
    Node* root;

    Node* insertRecursive(Node* current, int value) {
        if (current == nullptr) {
            return new Node(value);
        }

        if (value < current->data) {
            current->left = insertRecursive(current->left, value);
        } else if (value > current->data) {
            current->right = insertRecursive(current->right, value);
        }

        return current;
    }

public:
    BinarySearchTree() : root(nullptr) {}

    void insert(int value) {
        root = insertRecursive(root, value);
    }
};

int main() {
    BinarySearchTree bst;
    
    bst.insert(50);
    bst.insert(30);
    bst.insert(70);
    bst.insert(20);
    bst.insert(40);
    
    return 0;
}

Leave a Comment