사이클이 없는 연결된 그래프(acyclic connected graph)
트리의 루트(root) 유무에 따라 의미하는 트리가 다를 수 있으니 주의해야 함
트리의 사용
그래프에서의 정점을 트리에서는 노드라고 함
출처: https://gmlwjd9405.github.io/2018/08/12/data-structure-tree.html
루트 노드(root node): 부모가 없는 노드
내부 노드(internal node): 루트 노드, 리프 노드를 제외한 노드
리프 노드(leaf node): 차수가 0인 노드
부모(parent) - 자식(child) 관계: 위 그림에서 노드 A(부모)와 노드 B(자식)과 같은 관계를 부모-자식 관계로 볼 수 있음
조상(ancestor) - 자손(descendant) 관계: 위 그림에서 노드 A(조상)과 노드 H(자손)과 같은 관계를 조상-자손 관계로 볼 수 있음
서브 트리(subtree): 어떤 노드의 자식이 이루는 트리
어떤 노드의 자식 노드 개수
트리의 차수는 트리에 있는 노드의 최대 차수를 의미
루트의 레벨을 1로 하고 자식으로 내려가면서 하나씩 더해지는 개념
어떤 트리의 깊이 혹은 높이는 트리가 가지는 최대 레벨을 의미
대체로 루트 레벨은 0 또는 1 로 설정한다.
루트를 가지지 않는 일반적인 트리에서 노드의 개수가 n, 에지의 개수가 e일 때 아래와 같은 식이 성립한다.
e > n-1이 되는 순간 트리에 사이클이 생긴다고 볼 수 있다.
트리를 구성하는 노드의 자식이 최대 2개인 트리
자식이 없는 경우, 자식을 하나 가진 경우, 자식을 둘 가진 경우로 총 3가지를 고려할 수 있다.
왼쪽 자식, 오른쪽 자식으로 구분
트리도 그래프의 일종이기 때문에 DFS, BFS를 이용하여 순회해본다.
DFS → 전위 순회, 중위 순회, 후위 순회
BFS → 레벨 순서 순회
트리 노드 구현
class TreeNode:
def __init__(self, data=None):
self.__data = data
self.__left = None
self.__right = None
def __def__(self):
print('data{} is deleted'.format(self.__Data))
@property
def data(self):
return self.__data
@data.setter
def data(self, data):
self.__data = data
@property
def left(self):
return self.__left
@left.setter
def left(self, left):
self.__left = left
@property
def right(self):
return self.__right
@right.setter
def right(self, right):
self.__right = right
현재 노드 → 왼쪽 서브 트리 → 오른쪽 서브 트리
def preorder(cur):
# 현재 노드가 empty node 라면
if not cur:
return
# 방문
print(cur.data, end=' ')
preorder(cur.left)
preorder(cur.right)
def iter_preorder(cur):
s = Stack()
while True:
while cur:
print(cur.data, end=' ')
s.push(cur)
cur = cur.left
cur = s.pop()
if not cur:
break
cur = cur.right
왼쪽 서브 트리 → 현재 노드 → 오른쪽 서브 트리
def inorder(cur):
# 현재 노드가 empty node 라면
if not cur:
return
inorder(cur.left)
# 방문
print(cur.data, end=' ')
inorder(cur.right)
def iter_inorder(cur):
s = Stack()
while True:
while cur:
s.push(cur)
cur = cur.left
cur = s.pop()
if not cur:
break
print(cur.data, end=' ')
cur = cur.right
왼쪽 서브 트리 → 오른쪽 서브 트리 → 현재 노드
def postorder(cur):
# 현재 노드가 empty node 라면
if not cur:
return
postorder(cur.left)
postorder(cur.right)
print(cur.data, end=' ')
큐를 사용하는 순회 방법, BFS 일종
def levelorder(cur):
q = Queue()
q.put(cur)
while not q.empty():
cur = q.get()
# 방문
print(cur.data, end=' ')
# 현재 노드의 왼쪽 자식이 있다면 큐에 추가
if cur.left:
q.put(cur.left)
# 현재 노드의 오른쪽 자식이 있다면 큐에 추가
if cur.right:
q.put(cur.right)