Study/SWEA

[SWEA] [파이썬 SW 문제해결 기초] 6. Tree

줴림 2025. 4. 7. 22:49

[Tree]

- 비선형 구조 + 원소들 간에 1:n 관계를 가지는 자료구조
- 원소들 간에 계층 관계를 가지는 계층형 자료구조
- 상위 원소에서 하위 원소로 내려가면서 확장되는 Tree 모양의 구조
- 한 개 이상의 노드로 이루어진 유한 집합
  ⇒ 루트(Root): 노드 중 최상위 노드
  나머지 노드들: n(>=0)개의 분리 집합 T1, ... ,TN으로 분리될 수 있음
- T1, ..., TN은 각각 하나의 트리가 되며(재귀적 정의), 루트의 서브트리라고 함

노드(node): 트리의 원소
간선(edge): 부모 노드와 자식 노드를 연결

구성요소 설명
루트 노드 (Root node) 트리의 시작 노드
형제 노드 (Sibling node) 같은 부모 노드의 자식 노드들
조상 노드 (Ancestor node) 간선을 따라 루트 노드까지 이르는 경로에 있는 모든 노드들
서브트리 (SubTree) 부모 노드와 연결된 간선을 끊었을 때 생성되는 트리
자손 노드 (Descendent node) 서브트리에 있는 하위 레벨의 노드들

※ 차수(degree)
- 의미: 노드에 연결된 자식 노드의 수
- 트리의 차수: 트리에 있는 노드의 차수 중에서 가장 큰 값
- 단말 노드(리프 노드): 차수가 0인 노드 / 자식 노드가 없는 노드
※ 높이
- 노드의 높이: 노드의 레벨
- 트리의 높이: 트리에 있는 노드의 높이 중에서 가장 큰 값 (= 최대 레벨)

 

[Binary Tree]

- 모든 노드들이 2개의 서브트리를 갖는 특별한 형태의 트리
- 노드가 자식 노드를 최대한 2개까지만 가질 수 있는 트리
- 레벨 i에서의 노드의 최대 개수: 2^i개
- 높이가 h인 이진트리가 가질 수 있는 노드의 최소 개수: h+1개 / 최대 개수: 2^(h+1)-1개

※ 포화 이진 트리 (Full Binary Tree)
- 모든 레벨에 노드가 포화상태로 차 있는 이진 트리
- 최대의 노드 개수인 (2^(h+1)-1)의 노드를 가진 이진 트리
- 루트를 1번으로 하여 2^(h+1)-1까지 정해진 위치에 대한 노드 번호를 가짐

※ 완전 이진 트리 (Complete Binary Tree)
- 높이가 h이고 노드 수가 n개일 때 (단 2^h <= n < 2^(h+1)-1), Full 이진 트리의 노드 번호 1번부터 n번까지 빈 자리가 없는 이진 트리

※ 편향 이진 트리 (Skewed Binary Tree)
- 높이 h에 대한 최소 개수의 노드를 가지면서 한 쪽 방향의 자식 노드만을 가진 이진 트리

※ 순회(Traversal)
- 트리의 각 노드를 중복되지 않게 전부 방문하는 것
- 트리는 비선형 구조 => 선후 연결 관계를 알 수 없으므로 특별한 방법 필요

이름 방법
전위 순회 (Preorder traversal) Root → Left → Right
자손 노드보다 루트 노드를 먼저 방문
중위 순회 (Inorder traversal) Left → Root → Right
왼쪽 자손, 루트, 오른쪽 자손 순으로 방문
후위 순회 (Postorder traversal) Left → Right → Root
루트 노드보다 자손을 먼저 방문
# 전위 순회
def preorder_traverse(T):
  if T:				# T is not None
    visit(T)			# print(T.item)
    preorder_traverse(T.left)
    preorder_traverse(T.right)
    

# 중위 순회
def inorder_traverse(T):
  if T:				# T is not None
    inorder_traverse(T.left)
    visit(T)			# print(T.item)
    inorder_traverse(T.right)


# 후위 순회
def postorder_traverse(T):
  if T:				# T is not None
    postorder_traverse(T.left)
    postorder_traverse(T.right)
    visit(T)			# print(T.item)

 

 

[Expression Tree]

※ 리스트를 이용한 이진 트리의 표현
1) 이진 트리에 각 노드 번호를 다음과 같이 부여
2) 루트의 번호를 1로 함
3) 레벨 n에 있는 노드에 대하여 왼쪽부터 오른쪽으로 2n부터 2^(n+1)-1까지 번호를 차례로 부여 
4) 노드 번호를 리스트의 인덱스로 사용
5) 높이가 h인 이진 트리를 위한 리스트 크기는?
- 레벨 i의 최대 노드 수: 2^i

※ 노드 번호의 성질?
1) 노드 번호가 i인 노드의 부모 노드 번호: i // 2
2) 노드 번호가 i인 노드의 왼쪽 자식의 노드 번호: 2 * i
3) 노드 번호가 i인 노드의 오른쪽 자식의 노드 번호: 2 * i + 1 

 

[Binary Search Tree]

- 탐색 작업을 효율적으로 하기 위한 자료구조
- 모든 원소는 서로 다른 유일한 키를 가짐
- key(왼쪽 서브트리): 루트보다 작은 값 < key(루트 노드) < key(오른쪽 서브트리): 루트보다 큰 값
- 왼쪽 서브트리, 오른쪽 서브트리 => 이진 탐색 트리
- 중위순회하면 오름차순으로 정렬된 값을 얻을 수 있음

※ 탐색 연산
1) 루트에서 시작
2) 탐색할 키값 x를 루트 노드의 키값과 비교
- 키값 x = 루트 노드의 키값: 원하는 원소를 찾았으므로 탐색 연산 성공
- 키값 x < 루트 노드의 키값: 루트 노드의 왼쪽 서브트리에 대해서 탐색 연산 수행
- 키값 x > 루트 노드의 키값: 루트 노드의 오른쪽 서브트리에 대해서 탐색 연산 수행 
3) 서브트리에 대해서 순환적으로 탐색 연산을 반복
※ 삽입 연산
1) 먼저 탐색 연산을 수행
- 삽입할 원소와 같은 원소가 트리에 있으면 삽입할 수 없음 => 같은 원소가 트리에 있는지 탐색하여 확인
- 탐색에서 탐색 실패가 결정되는 위치가 삽입 위치가 됨
2) 탐색 실패한 위치에 원소를 삽입
※ BST의 성능
- 탐색, 삽입, 삭제 시간: 트리의 높이에 좌우됨 => O(h)
- 평균의 경우: 이진 트리가 균형적으로 생성되어 있는 경우 => O(log n)
- 최악의 경우: 한쪽으로 치우친 경사 이진 트리의 경우 => O(n)

 

[Heap]

- 완전 이진 트리에 있는 노드 중에서 키값이 가장 큰 노드나 가장 작은 노드를 찾기 위해 만든 자료구조

최대 힙 (Max heap) 최소 힙 (Min heap)
키값이 가장 큰 노드를 찾기 위한 완전 이진 트리
부모 노드의 키값 > 자식 노드의 키값
루트 노드: 키값이 가장 큰 노드
키값이 가장 작은 노드를 찾기 위한 완전 이진 트리
부모 노드의 키값 < 자식 노드의 키값
루트 노드: 키값이 가장 작은 노드

삽입 연산: 비어 있는 곳에 임시로 삽입하고 부모 노드와 비교해가며 위치 바꾸기
삭제 연산: 루트 노드의 원소 삭제 → 마지막 노드를 루트 노드 위치로 이동 → 자식 노드와 비교해가며 위치 바꾸기