Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

파이썬으로 이진 트리가 레드-블랙 트리처럼 높이 균형을 이루는지 확인하는 방법

레드-블랙 트리의 높이 균형 조건

레드-블랙 트리(Red-Black Tree)와 같은 자가 균형 트리에서는 임의의 노드가 가질 수 있는 최대 높이가 최소 높이의 두 배를 넘지 않습니다. 이러한 특성 덕분에 트리의 탐색·삽입·삭제 연산이 항상 O(log n)의 시간 복잡도를 유지할 수 있습니다.

따라서 하나의 이진 탐색 트리(Binary Search Tree)가 주어졌을 때, 그 트리가 높이 균형을 이루고 있는지 확인하려면 다음 성질을 검사해야 합니다.

모든 노드에 대해, 그 노드에서 가장 깊은 리프까지의 경로(최장 경로)에 있는 노드 수는 가장 얕은 리프까지의 경로(최단 경로)에 있는 노드 수의 두 배를 초과하지 않아야 한다.

문제 예시

예를 들어 다음과 같은 트리가 입력으로 주어졌다고 가정해 보겠습니다.

파이썬으로 이진 트리가 레드-블랙 트리처럼 높이 균형을 이루는지 확인하는 방법

위 트리에서 루트 노드 10을 기준으로 하면, 최장 경로는 10 → 100 → 50 → 40으로 높이가 4이고, 최단 경로는 10 → 5로 높이가 2입니다. 최장 높이 4가 최단 높이 2의 두 배인 4 이하이므로 이 트리는 균형이 잡혀 있으며, 출력은 True가 됩니다.

풀이 접근 방법

이 문제는 후위 순회(post-order) 방식의 재귀 함수로 해결할 수 있습니다. 단계별 과정은 다음과 같습니다.

  1. solve() 함수 정의 — 매개변수로 root, max_height, min_height를 받습니다.
  2. root가 None이라면:
    • max_height = 0, min_height = 0으로 설정하고
    • True를 반환합니다. (빈 서브트리는 항상 균형 상태)
  3. 왼쪽 서브트리용 변수 초기화: left_max = 0, left_min = 0
  4. 오른쪽 서브트리용 변수 초기화: right_max = 0, right_min = 0
  5. solve(root.left, left_max, left_min)의 결과가 False이면 False를 반환합니다.
  6. solve(root.right, right_max, right_min)의 결과가 False이면 False를 반환합니다.
  7. max_height = max(left_max, right_max) + 1로 현재 노드의 최대 높이를 계산합니다.
  8. min_height = min(left_min, right_min) + 1로 현재 노드의 최소 높이를 계산합니다.
  9. max_height <= 2 × min_height를 만족하면 True를, 그렇지 않으면 False를 반환합니다.

메인 호출부에서는 max_height와 min_height를 0으로 초기화한 뒤 solve(root, max_height, min_height)를 호출하여 최종 결과를 얻습니다.

파이썬 구현 예제

다음 구현을 통해 더 잘 이해할 수 있습니다.

class TreeNode:
    def __init__(self, key):
        self.data = key
        self.left = None
        self.right = None

def solve(root, max_height, min_height):
    if (root == None):
        max_height = min_height = 0
        return True
    left_max = 0
    left_min = 0
    right_max, right_min = 0, 0
    if (solve(root.left, left_max, left_min) == False):
        return False
    if (solve(root.right, right_max, right_min) == False):
        return False
    max_height = max(left_max, right_max) + 1
    min_height = min(left_min, right_min) + 1
    if (max_height <= 2 * min_height):
        return True
    return False

def is_tree_balanced(root):
    max_height, min_height = 0, 0
    return solve(root, max_height, min_height)

root = TreeNode(10)
root.left = TreeNode(5)
root.right = TreeNode(100)
root.right.left = TreeNode(50)
root.right.right = TreeNode(150)
root.right.left.left = TreeNode(40)

print(is_tree_balanced(root))

입력

root = TreeNode(10)
root.left = TreeNode(5)
root.right = TreeNode(100)
root.right.left = TreeNode(50)
root.right.right = TreeNode(150)
root.right.left.left = TreeNode(40)

출력

True

핵심 포인트 정리

  • 재귀적 검사: 각 노드에서 왼쪽·오른쪽 서브트리의 최대/최소 높이를 재귀적으로 구한 뒤, 현재 노드 기준으로 균형 조건(max_height ≤ 2 × min_height)을 검사합니다.
  • 조기 종료: 어느 한쪽 서브트리라도 균형이 깨져 있다면 즉시 False를 반환하여 불필요한 연산을 줄일 수 있습니다.
  • 실전 팁: 파이썬에서는 정수가 값으로 전달되므로, 실무 코드에서는 solve()가 (균형 여부, 최대 높이, 최소 높이)를 튜플로 반환하도록 작성하면 부모 노드가 자식의 높이 정보를 확실하게 받을 수 있어 더 안전합니다.
  • 시간 복잡도: 모든 노드를 한 번씩 방문하므로 전체 시간 복잡도는 O(n)입니다.