CS/자료구조

[자료구조] #15 Tree(2)

태연한 컴공생 2024. 5. 30. 20:24

• 이진 트리의 순회

 

순회는 자료구조 내의 데이터를 특정 순서대로 방문하는 것을 의미한다.

 

선형 자료구조에서의 순회

선형적인 순서로 조회한다.

이진 트리에서의 순회

트리는 비선형 자료구조이기 때문에 여러가지 순서로 노드를 방문할 수 있다.

 

• 이진 트리의 순회 방법

 

전위 순회(pre-order traversal)

루트 출력 → 왼쪽 서브트리 → 오른쪽 서브트리

def preorder(node):
    if node is not NULL:            # 현재 노드가 NULL이 아닌 경우에만 수행
        print(node.data)            # 현재 노드의 데이터를 출력
        preorder(node.left)         # 왼쪽 자식 노드를 전위 순회
        preorder(node.right)        # 오른쪽 자식 노드를 전위 순회

 

중위 순회(in-order traversal)

왼쪽 서브트리 → 루트 출력 → 오른쪽 서브트리

def inorder(node):
    if node is not NULL:             # 현재 노드가 NULL이 아닌 경우에만 수행
        inorder(node.left)           # 왼쪽 자식 노드를 중위 순회
        print(node.data)             # 현재 노드의 데이터를 출력
        inorder(node.right)          # 오른쪽 자식 노드를 중위 순회

 

후위 순회(post-order traversal)

왼쪽 서브트리 → 오른쪽 서브트리 → 루트 출력

def postorder(node):
    if node is not NULL:              # 현재 노드가 NULL이 아닌 경우에만 수행
        postorder(node.left)          # 왼쪽 자식 노드를 후위 순회
        postorder(node.right)         # 오른쪽 자식 노드를 후위 순회
        print(node.data)              # 현재 노드의 데이터를 출력

 

레벨 순회(level-order traversal)

레벨 순서로 노드를 방문한다.

 

Root(A)를 시작점으로 BFS(너비 우선 탐색)을 하면 된다.

BFS를 위해서 큐를 사용해야 한다.

def levelorder():
    initialize Q;                      # 큐 Q를 초기화
    Q.enqueue(root);                   # 루트 노드를 큐에 추가
    while Q is not empty:              # 큐가 비어 있지 않는 동안 반복
        cur_node = Q.dequeue();        # 큐의 맨 앞 노드를 제거하여 현재 노드로 설정
        if cur_node is not NULL:       # 현재 노드가 NULL이 아닌 경우에만 수행
            print(cur_node.data)       # 현재 노드의 데이터를 출력
            Q.enqueue(cur_node.left);  # 왼쪽 자식 노드를 큐에 추가
            Q.enqueue(cur_node.right); # 오른쪽 자식 노드를 큐에 추가

 

• 순회를 이용한 이진 트리의 연산

 

후위 순회를 응용한 소멸자

왼쪽/오른쪽 서브 트리의 노드들이 동적해제가 먼저되고 현재 노드를 해제해야 한다.

// BinaryTree 클래스의 소멸자
BinaryTree::~BinaryTree(){
    removesNodes(this->root);  // 루트 노드부터 시작하여 모든 노드를 제거
}

// 트리의 모든 노드를 후위 순회 방식으로 제거하는 재귀 함수
void BinaryTree::removeNodes(BinaryNode* node){
    if(node != nullptr){          // 현재 노드가 nullptr이 아닌 경우에만 수행
        removesNodes(node->getLeft());   // 왼쪽 자식 노드를 재귀적으로 제거
        removesNodes(node->getRight());  // 오른쪽 자식 노드를 재귀적으로 제거
        delete node;                     // 현재 노드를 삭제하여 메모리 해제
    }
}

 

getCount : 노드 개수 세기

각 서브 트리의 노드의 수와 자기 자신을 합하고 반환한다.

// BinaryTree 클래스의 노드 개수를 반환하는 함수
int BinaryTree::getCount() {
    return (this->empty()) ? 0 : getCount(this->root);  
// 트리가 비어 있으면 0을 반환, 그렇지 않으면 루트 노드에서 시작
}

// 특정 노드에서 시작하여 모든 하위 노드의 개수를 세는 재귀 함수
int BinaryTree::getCount(BinaryNode* node) {
    if (node == nullptr) return 0;      // 현재 노드가 nullptr이면 0을 반환
    int cnt = getCount(node->getLeft());  // 왼쪽 하위 트리의 노드 수를 셈
    cnt += 1;                            // 현재 노드를 포함하여 1 증가
    cnt += getCount(node->getRight());   // 오른쪽 하위 트리의 노드 수를 셈
    return cnt;                          // 전체 하위 트리의 노드 수를 반환
}

 

getLeafCount : 리프 노드 개수 세기

1. 전역변수를 두고 순회를 하면서 만나는 노드가 리프인지를 카운트한다.

2. 각 서브트리의 리프 노드의 수를 합하고 반환한다.

 

// BinaryTree 클래스의 리프 노드 개수를 반환하는 함수
int BinaryTree::getLeafCount() {
    return (this->empty()) ? 0 : getLeafCount(this->root);  
// 트리가 비어 있으면 0을 반환, 그렇지 않으면 루트 노드에서 시작
}

// 특정 노드에서 시작하여 모든 하위 노드의 리프 노드 개수를 세는 재귀 함수
int BinaryTree::getLeafCount(BinaryNode* node) {
    if (node == nullptr) return 0;      // 현재 노드가 nullptr이면 0을 반환
    if (node->isLeaf()) return 1;       // 현재 노드가 리프 노드이면 1을 반환
    // 왼쪽 하위 트리와 오른쪽 하위 트리의 리프 노드 수를 합산하여 반환
    return getLeafCount(node->getLeft()) + getLeafCount(node->getRight());
}

 

getHeight : 트리의 높이

트리의 높이는 서브 트리의 최대 높이 + 1이다.

// BinaryTree 클래스의 트리 높이를 반환하는 함수
int BinaryTree::getHeight() {
    return getHeight(root);  // 루트 노드에서 시작하여 높이를 계산
}

// 특정 노드에서 시작하여 하위 트리의 높이를 계산하는 재귀 함수
int BinaryTree::getHeight(BinaryNode *node) {
    if (node == nullptr) return -1;      // 현재 노드가 nullptr이면 -1 반환 (빈 트리의 높이)
    int hLeft = getHeight(node->getLeft());  // 왼쪽 하위 트리의 높이 계산
    int hRight = getHeight(node->getRight());  // 오른쪽 하위 트리의 높이 계산
    return 1 + max(hLeft, hRight);       // 더 큰 높이에 1을 더하여 반환 (현재 노드를 포함)
}

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

[자료구조] #17 Binary Search Tree(2)  (0) 2024.06.02
[자료구조] #16 Binary Search Tree(1)  (0) 2024.06.02
[자료구조] #14 Tree(1)  (0) 2024.05.30
[자료구조] #12 Recursion(1)  (0) 2024.05.29
[자료구조] #10 List(1)  (0) 2024.05.02