일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- 스프링 타입컨버터
- 김영한
- 서블릿
- 언체크에러
- 의존관계
- 스프링 파일 업로드
- 커밋로그
- 객체지향
- BeanValidation
- 예외추상화
- 체크에러
- http
- HTTP 요청 메시지
- DI
- BeanDefnition
- BasicErrorController
- 깃허브 저장소 합치기
- HTTP 응답 메시지
- 웹 스코프
- REST #REST API #HTTP 메서드
- HTTP메시지
- ExceptionResolver
- 프로토콜 스택 4계층
- 스프링 빈
- 백준4256
- 스프링
- 스프링 예외변환기
- 프로토타입 스코프
- 스프링 컨테이너
- 백준 2263
Archives
- Today
- Total
Enthusiasm! Enthusiasm!
이진 트리의 순회 본문
대표적인 자료구조인 트리에서 이진트리를 순회하는 방법 및 간단한 코드를 소개하겠다.
이진 트리(Binart Tree)
트리란 각 노드가 부모-자녀 관계를 갖는 계층 구조를 나타낸 데이터 구조이며, 루트 노드에서 시작하여 하위 노드로 분기되는 비선형 데이터 구조이다. 리프 노드를 제외한 각 노드에는 하나 이상의 하위 노드가 있다.
이진트리는 이러한 트리 구조중 각 노드들이 자식을 2개 이하로 가지는 트리를 칭한다.
이진 트리의 순회
이진 트리를 순회하는 방법은 대표적으로 3가지가 있다.(백준 1991)
preorder(전위 순회)
-(루트)(왼쪽 자식)(오른쪽 자식) 순서로 순회
def preorder(curr):
if curr != '.': #현재 노드가 null이 아니면 (여기서는 .을 null이라 가정)
print(curr, end= '')
preorder(tree[curr][0]) #왼쪽 자식
preorder(tree[curr][1]) #오른쪽 자식
-위 예시에서 탐색 결과는 3->6->5->4->8->7->1->2
inorder(중위 순회)
-(왼쪽 자식)(루트)(오른쪽 자식) 순서로 순회
def inorder(curr):
if curr != '.':
inorder(tree[curr][0])
print(curr, end='')
inorder(tree[curr][1])
-위 예시에서 탐색 결과는 5->6->8->4->3->1->2->7
postorder(후위 순회)
-(왼쪽 자식)(오른쪽 자식)(루트) 순서로 순회
def postorder(curr):
if curr != '.':
postorder(tree[curr][0])
postorder(tree[curr][1])
print(curr, end='')
-위 예시에서 탐색 결과는 5->8->4->6->2->1->7->3
두 순회 결과로 트리 구조 얻기 (백준 2263, 4256)
inorder와 preorder 또는 inorder와 postorder의 순회 결과를 알면 트리의 구조를 알 수 있다.
- inorder + preorder
- preorder는 루트노드 부터 탐색을 시작한다는 성질(첫번째 값이 루트)과 inorder의 탐색 순서인 (왼쪽 자식)(루트)(오른쪽 자식)을 이용하여 분할 정복한다.
- preorder에서 루트 노드를 구한 뒤, inorder에서 루트를 기준으로 왼쪽 서브트리와 오른쪽 서브트리로 나눈다.
- 각 서브트리의 시작 index와 끝 index를 이용하여 해당 범위에 대해 1번을 시행한다. (서브트리에서 각각 루트 노드를 구한 뒤, 루트를 기준으로 다시 왼쪽 서브트리와 오른쪽 서브트리로 나눈다.) 이 때, preorder에서는 시작노드가 루트가 되므로 다음 탐색에서 시작노드가 제외되고 inorder에서는 끝 노드가 루트이므로 끝 노드가 제외되므로 index를 구할 때 주의해야한다.
- 이 과정을 반복하여 분할 정복하면 트리의 구조를 알 수 있다.
- preorder는 루트노드 부터 탐색을 시작한다는 성질(첫번째 값이 루트)과 inorder의 탐색 순서인 (왼쪽 자식)(루트)(오른쪽 자식)을 이용하여 분할 정복한다.
def makePost(preStart, preEnd, inStart, inEnd):
if (preStart > preEnd) or (inStart > inEnd):
return
root = preorder[preStart] #preorder의 시작 노드가 루트
rootIndex = nodeIndex[root] #inorder에서 root의 index
leftCount = rootIndex - inStart #왼쪽 서브트리 노드의 개수
rightCount = inEnd - rootIndex #오른쪽 서브트리 노드의 개수
makePost(preStart + 1, preStart + leftCount, inStart, inStart + leftCount - 1) #왼쪽 서브트리에 대해 탐색
makePost(preEnd - rightCount + 1, preEnd, inEnd - rightCount + 1, inEnd) #오른쪽 서브트리에 대해 탐색
print(root)
- inorder + postorder
- postorder의 맨 끝 노드가 루트노드임을 이용하여 위 방식과 마찬가지로 구현하면 된다.
def makePre(inStart,inEnd,postStart,postEnd):
if (inStart > inEnd) or (postStart > postEnd):
return
root = postorder[postEnd] #postorder의 끝 노드가 루트
print(root)
rootIndex = nodeIndex[root] #inorder에서 root의 index
leftCount = rootIndex - inStart #왼쪽 서브트리 노드의 개수
rightCount = inEnd - rootIndex #오른쪽 서브트리 노드의 개수
makePre(inStart, inStart + leftCount - 1, postStart, postStart + leftCount - 1)
makePre(inEnd - rightCount + 1, inEnd, postEnd - rightCount, postEnd - 1)
'자료구조&알고리즘 > 자료구조 및 알고리즘' 카테고리의 다른 글
재귀 vs 비트마스킹 (1) | 2023.11.02 |
---|
Comments