Chapter 08
이진 트리
Binary Tree
Part 1  이진 트리의 기본 · Binary Tree Basics
Part 2  이진 탐색 트리 구현 · Binary Search Tree Implementation
Part 3  이진 탐색 트리 응용 · BST Applications
01
Part 1
이진 트리의 기본
Binary Tree Basics
트리의 개념, 용어, 노드 구조, 그리고 순회를 학습합니다.

생활 속 트리 구조

Tree Structures in Daily Life
한국어

우리 주변의 트리

트리 구조란 나무를 거꾸로 뒤집어 놓은 형태의 자료구조입니다.

회사 조직도

사장을 최상위로, 그 아래 부서장, 팀원 등이 계층 구조를 이루는 형태입니다.

컴퓨터 폴더 구조

상위 폴더 안에 하위 폴더들이 계속 이어져 있는 구조입니다. C:\Users\Documents 처럼 경로가 만들어집니다.

가계도

조상부터 시작하여 자손이 아래로 이어지는 형태도 트리 구조입니다.

사장 개발부장 영업부장 팀원A 팀원B 팀원C
English

Trees Around Us

A tree structure is a data structure shaped like an upside-down tree.

Company Org Chart

The CEO is at the top, followed by department heads and team members forming a hierarchical structure.

Computer Folder Structure

Subfolders are nested inside parent folders. Paths like C:\Users\Documents are formed this way.

Family Tree

Starting from ancestors, descendants branch out downward — another tree structure.

Key Insight

Trees are everywhere: file systems, HTML DOM, database indexes, AI decision trees — they all use tree structures!

트리 용어와 이진 트리

Tree Terminology & Binary Tree Concept
한국어

트리 자료구조 용어

용어설명
루트(Root)트리의 최상위 노드
부모(Parent)상위에 연결된 노드
자식(Child)하위에 연결된 노드
리프(Leaf)자식이 없는 맨 아래 노드
서브 트리특정 노드 아래의 부분 트리
레벨(Level)루트를 0으로 하여 내려갈 때 증가
높이(Height)트리의 최대 레벨

이진 트리란?

모든 노드의 자식이 최대 2개인 트리입니다. 각 노드는 왼쪽 자식과 오른쪽 자식만 가질 수 있습니다.

루트 부모 노드 리프 리프 리프 Level 0 Level 1 Level 2
English

Tree Data Structure Terms

TermDescription
RootThe topmost node of the tree
ParentA node connected above
ChildA node connected below
LeafA node with no children (bottom)
SubtreeA partial tree below a given node
LevelIncreases from 0 (root) going down
HeightMaximum level of the tree

What is a Binary Tree?

A tree where every node has at most 2 children. Each node can have only a left child and a right child.

Binary = "Two"

The word "binary" means two. A binary tree limits each node to a maximum of two branches — left and right.

이진 트리의 종류

Types of Binary Trees
한국어

이진 트리의 세 가지 유형

포화 이진 트리 (Full Binary Tree)

모든 레벨의 노드가 꽉 차 있는 트리. 리프 노드가 모두 같은 레벨에 있습니다.

완전 이진 트리 (Complete Binary Tree)

마지막 레벨을 제외한 모든 레벨이 꽉 차 있고, 마지막 레벨은 왼쪽부터 채워진 트리입니다.

편향 이진 트리 (Skewed Binary Tree)

한쪽으로만 노드가 이어진 트리. 왼쪽 편향 또는 오른쪽 편향이 있습니다.

포화 이진 트리 A B C 완전 이진 트리 A B C 편향 이진 트리 A B C
English

Three Types of Binary Trees

Full Binary Tree

Every level is completely filled. All leaf nodes are at the same level.

Complete Binary Tree

All levels are full except possibly the last, which is filled from left to right.

Skewed Binary Tree

Nodes extend in only one direction — left-skewed or right-skewed. Essentially a linked list.

Performance Warning

A skewed tree has O(n) search time — the same as a linked list. A balanced tree gives O(log n). That's the difference between searching 1,000,000 nodes in 1M steps vs. 20 steps!

노드 구조와 이진 트리 생성

Node Structure & Building a Binary Tree
한국어

이진 트리 노드 구조

이진 트리의 노드는 세 부분으로 구성됩니다: 왼쪽 링크(left), 데이터(data), 오른쪽 링크(right).

left data right

TreeNode 클래스

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

트리 생성 과정 (Code08-01)

## 노드 6개로 완전 이진 트리 생성 ## node1 = TreeNode() node1.data = '화사' node2 = TreeNode() node2.data = '솔라' node1.left = node2 node3 = TreeNode() node3.data = '문별' node1.right = node3 node4 = TreeNode() node4.data = '휘인' node2.left = node4 node5 = TreeNode() node5.data = '쯔위' node2.right = node5 node6 = TreeNode() node6.data = '선미' node3.left = node6 print(node1.data) print(node1.left.data, node1.right.data) print(node1.left.left.data, node1.left.right.data, node1.right.left.data)
English

Binary Tree Node Structure

Each node has three parts: left link, data, and right link.

TreeNode Class

We define a simple class with three attributes: left (pointer to left child), data (the value stored), and right (pointer to right child). Initially all are None.

Building Step by Step

1Create root node node1 with data '화사'
2Create node2 ('솔라'), set as root's left child
3Create node3 ('문별'), set as root's right child
4Create node4 ('휘인'), node5 ('쯔위'), node6 ('선미') and link them to their parents

Output

화사
솔라 문별
휘인 쯔위 선미

Navigation

node1.left.right.data means: from root → go left → go right → read data. This chain-style access is fundamental to tree traversal.

이진 트리 순회

Binary Tree Traversal
한국어

순회(Traversal)란?

이진 트리의 모든 노드를 한 번씩 방문하는 것을 순회라고 합니다. 데이터 처리 순서에 따라 세 가지로 나뉩니다.

순회 방식순서기억법
전위 순회현재 → 왼쪽 → 오른쪽왼오
중위 순회왼쪽 → 현재 → 오른쪽
후위 순회왼쪽 → 오른쪽 → 현재왼오
화사 솔라 문별 휘인 쯔위 선미

순회 결과

전위: 화사→솔라→휘인→쯔위→문별→선미

중위: 휘인→솔라→쯔위→화사→선미→문별

후위: 휘인→쯔위→솔라→선미→문별→화사

English

What is Traversal?

Traversal means visiting every node exactly once. Three methods differ by when the current node is processed.

TraversalOrderMnemonic
PreorderRoot → Left → RightRLR
InorderLeft → Root → RightLRR
PostorderLeft → Right → RootLRR

Recursive Pattern

All three traversals use the same recursive structure — only the position of print(node.data) changes!

Results

Pre: 화사→솔라→휘인→쯔위→문별→선미

In: 휘인→솔라→쯔위→화사→선미→문별

Post: 휘인→쯔위→솔라→선미→문별→화사

순회 코드 구현

Traversal Code Implementation
한국어

세 가지 순회 함수 (Code08-02)

def preorder(node): if node == None: return print(node.data, end='->') preorder(node.left) preorder(node.right) def inorder(node): if node == None: return inorder(node.left) print(node.data, end='->') inorder(node.right) def postorder(node): if node == None: return postorder(node.left) postorder(node.right) print(node.data, end='->')

핵심 포인트

print()의 위치만 다릅니다! 전위는 맨 위, 중위는 중간, 후위는 맨 아래에 놓습니다. 재귀 호출이 트리를 자동으로 탐색합니다.

English

Three Traversal Functions

The Secret

The only difference is where print() is placed:

Preorder: print BEFORE recursive calls

Inorder: print BETWEEN recursive calls

Postorder: print AFTER recursive calls

Base Case

if node == None: return stops the recursion when we reach an empty child. Without this, the function would crash with an AttributeError.

Output

전위 순회 : 화사->솔라->휘인->쯔위->문별->선미->끝
중위 순회 : 휘인->솔라->쯔위->화사->선미->문별->끝
후위 순회 : 휘인->쯔위->솔라->선미->문별->화사->끝

연습문제 Part 1

Practice Part 1
한국어
연습문제 1-1 : 이진 트리 생성과 출력

TreeNode 클래스로 6개 노드(화사, 솔라, 문별, 휘인, 쯔위, 선미)의 이진 트리를 만들고 레벨별로 출력하시오. (Code08-01)

class TreeNode(): def __init__(self): self.left = None self.data = None self.right = None node1 = TreeNode() node1.data = '화사' node2 = TreeNode() node2.data = '솔라' node1.left = node2 node3 = TreeNode() node3.data = '문별' node1.right = node3 node4 = TreeNode() node4.data = '휘인' node2.left = node4 node5 = TreeNode() node5.data = '쯔위' node2.right = node5 node6 = TreeNode() node6.data = '선미' node3.left = node6 print(node1.data, end=' ') print() print(node1.left.data, node1.right.data, end=' ') print() print(node1.left.left.data, node1.left.right.data, node1.right.left.data, end=' ')
연습문제 1-2 : 확장 트리 순회

8개 노드 트리(화사→솔라/문별, 솔라→휘인/쯔위, 문별→선미, 휘인→다현(오른쪽), 선미→사나(오른쪽))를 생성하고, 전위·중위·후위 순회 결과를 출력하시오. (Self08-01)

class TreeNode(): def __init__(self): self.left = None self.data = None self.right = None node1 = TreeNode(); node1.data = '화사' node2 = TreeNode(); node2.data = '솔라' node1.left = node2 node3 = TreeNode(); node3.data = '문별' node1.right = node3 node4 = TreeNode(); node4.data = '휘인' node2.left = node4 node5 = TreeNode(); node5.data = '쯔위' node2.right = node5 node6 = TreeNode(); node6.data = '선미' node3.left = node6 node7 = TreeNode(); node7.data = '다현' node4.right = node7 node8 = TreeNode(); node8.data = '사나' node6.right = node8 def preorder(node): if node == None: return print(node.data, end='->') preorder(node.left) preorder(node.right) def inorder(node): if node == None: return inorder(node.left) print(node.data, end='->') inorder(node.right) def postorder(node): if node == None: return postorder(node.left) postorder(node.right) print(node.data, end='->') print('전위 순회 : ', end='') preorder(node1); print('끝') print('중위 순회 : ', end='') inorder(node1); print('끝') print('후위 순회 : ', end='') postorder(node1); print('끝')
English
Practice 1-1 : Build & Print Binary Tree

Create a binary tree with 6 nodes (화사, 솔라, 문별, 휘인, 쯔위, 선미) using TreeNode class and print level by level. (Code08-01)

class TreeNode(): def __init__(self): self.left = None self.data = None self.right = None node1 = TreeNode() node1.data = '화사' node2 = TreeNode() node2.data = '솔라' node1.left = node2 node3 = TreeNode() node3.data = '문별' node1.right = node3 node4 = TreeNode() node4.data = '휘인' node2.left = node4 node5 = TreeNode() node5.data = '쯔위' node2.right = node5 node6 = TreeNode() node6.data = '선미' node3.left = node6 print(node1.data, end=' ') print() print(node1.left.data, node1.right.data, end=' ') print() print(node1.left.left.data, node1.left.right.data, node1.right.left.data, end=' ')

Output

화사
솔라 문별
휘인 쯔위 선미
Practice 1-2 : Extended Tree Traversal

Build an 8-node tree (adding 다현 as 휘인's right child, 사나 as 선미's right child) and print preorder, inorder, and postorder results. (Self08-01)

class TreeNode(): def __init__(self): self.left = None self.data = None self.right = None node1 = TreeNode(); node1.data = '화사' node2 = TreeNode(); node2.data = '솔라' node1.left = node2 node3 = TreeNode(); node3.data = '문별' node1.right = node3 node4 = TreeNode(); node4.data = '휘인' node2.left = node4 node5 = TreeNode(); node5.data = '쯔위' node2.right = node5 node6 = TreeNode(); node6.data = '선미' node3.left = node6 node7 = TreeNode(); node7.data = '다현' node4.right = node7 node8 = TreeNode(); node8.data = '사나' node6.right = node8 def preorder(node): if node == None: return print(node.data, end='->') preorder(node.left) preorder(node.right) def inorder(node): if node == None: return inorder(node.left) print(node.data, end='->') inorder(node.right) def postorder(node): if node == None: return postorder(node.left) postorder(node.right) print(node.data, end='->') print('전위 순회 : ', end='') preorder(node1); print('끝') print('중위 순회 : ', end='') inorder(node1); print('끝') print('후위 순회 : ', end='') postorder(node1); print('끝')

Expected Output

전위: 화사->솔라->휘인->다현->쯔위->문별->선미->사나->끝
중위: 휘인->다현->솔라->쯔위->화사->선미->사나->문별->끝
후위: 다현->휘인->쯔위->솔라->사나->선미->문별->화사->끝
02
Part 2
이진 탐색 트리 구현
Binary Search Tree Implementation
이진 탐색 트리의 생성, 검색, 삭제를 학습합니다.

이진 탐색 트리의 개념

Binary Search Tree Concept
한국어

이진 탐색 트리(BST)란?

데이터의 크기를 기준으로 정렬된 이진 트리입니다. 활용도가 매우 높습니다.

BST의 4가지 특징

  • 왼쪽 서브 트리는 루트 노드보다 모두 작은 값
  • 오른쪽 서브 트리는 루트 노드보다 모두 큰 값
  • 각 서브 트리도 위 특징을 만족
  • 모든 노드 값은 중복 불가
블랙핑크 레드벨벳 에이핑크 걸스데이 마마무 트와이스 작다 크다

한글은 가나다 순서로 비교합니다. '걸스데이' < '레드벨벳' < '마마무' < '블랙핑크' < '에이핑크' < '트와이스'

English

What is a BST?

A Binary Search Tree (BST) is a binary tree organized by data values for efficient searching.

4 Rules of a BST

  • Left subtree: all values smaller than root
  • Right subtree: all values larger than root
  • Each subtree also follows these rules
  • All values must be unique (no duplicates)
Why BST?

Searching a BST is like a binary search on a sorted array — at each node, you eliminate half the remaining data. Average search time is O(log n).

Korean String Comparison

Python compares Korean strings by their Unicode (가나다) order. So '걸스데이' < '블랙핑크' is True in Python.

이진 탐색 트리 생성

Building a Binary Search Tree
한국어

BST 생성 과정 (Code08-03)

배열의 데이터를 순서대로 BST에 삽입합니다.

class TreeNode(): def __init__(self): self.left = None self.data = None self.right = None memory = [] root = None nameAry = ['블랙핑크', '레드벨벳', '마마무', '에이핑크', '걸스데이', '트와이스'] # 첫 번째 데이터 → 루트 노드 node = TreeNode() node.data = nameAry[0] root = node memory.append(node) # 두 번째부터 자리 찾아 삽입 for name in nameAry[1:]: node = TreeNode() node.data = name current = root while True: if name < current.data: if current.left == None: current.left = node break current = current.left else: if current.right == None: current.right = node break current = current.right memory.append(node) print("이진 탐색 트리 구성 완료!")
English

BST Construction Process

1First element ('블랙핑크') becomes the root
2For each subsequent name, start at root
3If name < current → go left; else → go right
4When an empty spot (None) is found, insert there
Insertion Example

'레드벨벳' < '블랙핑크' → go left → left is None → insert as left child

'에이핑크' > '블랙핑크' → go right → right is None → insert as right child

'마마무' < '블랙핑크' → left → '마마무' > '레드벨벳' → right → None → insert

Key Pattern

The while True loop walks down the tree until it finds an empty slot. The comparison name < current.data decides left vs. right at each step.

이진 탐색 트리 검색

BST Search
한국어

데이터 검색 (Code08-04)

BST에서 '마마무'를 찾는 과정을 살펴봅니다.

1'마마무'를 루트('블랙핑크')와 비교 → 작으므로 왼쪽으로 이동
2'마마무'를 '레드벨벳'과 비교 → 크므로 오른쪽으로 이동
3'마마무' == '마마무' → 찾음!
findName = '마마무' current = root while True: if findName == current.data: print(findName, '을(를) 찾음.') break elif findName < current.data: if current.left == None: print(findName, '이(가) 트리에 없음') break current = current.left else: if current.right == None: print(findName, '이(가) 트리에 없음') break current = current.right
English

Data Search (Code08-04)

Searching follows the same left/right logic as insertion.

Search Algorithm

  • If findName == current.dataFound!
  • If findName < current.data → go left
  • If findName > current.data → go right
  • If next direction is NoneNot found
Search Efficiency

With 6 nodes, we found '마마무' in just 3 comparisons. In a balanced BST with 1,000,000 nodes, it takes at most ~20 comparisons!

Output

마마무 을(를) 찾음.

이진 탐색 트리 삭제

BST Node Deletion
한국어

노드 삭제의 세 가지 경우

Case 1: 리프 노드 삭제

자식이 없는 노드. 부모의 해당 링크를 None으로 설정하고 삭제합니다.

Case 2: 자식이 하나인 노드 삭제

왼쪽 또는 오른쪽 자식만 있는 경우. 부모의 링크를 자식 노드로 연결합니다.

Case 3: 자식이 둘인 노드 삭제

가장 복잡한 경우. 재귀를 사용해야 편리합니다.

삭제 코드 (Code08-05)

deleteName = '마마무' current = root parent = None while True: if deleteName == current.data: # Case 1: 리프 노드 if current.left == None \ and current.right == None: if parent.left == current: parent.left = None else: parent.right = None del(current) # Case 2a: 왼쪽 자식만 있음 elif current.left != None \ and current.right == None: if parent.left == current: parent.left = current.left else: parent.right = current.left del(current) # Case 2b: 오른쪽 자식만 있음 elif current.left == None \ and current.right != None: if parent.left == current: parent.left = current.right else: parent.right = current.right del(current) print(deleteName, '이(가) 삭제됨.') break elif deleteName < current.data: if current.left == None: print(deleteName, '이(가) 트리에 없음') break parent = current current = current.left else: if current.right == None: print(deleteName, '이(가) 트리에 없음') break parent = current current = current.right
English

Three Deletion Cases

Case 1: Leaf Node

No children. Simply set parent's link to None and delete the node.

Case 2: One Child

Only left or right child exists. Connect parent's link directly to the grandchild, bypassing the deleted node.

Case 3: Two Children

Most complex case — requires finding a replacement node (typically the inorder successor or predecessor).

Key: Track the Parent

We need both current (the node to delete) and parent (to re-link). The search loop updates parent = current before moving to the next node.

Output

마마무 이(가) 삭제됨.

연습문제 Part 2

Practice Part 2
한국어
연습문제 2-1 : BST 생성과 검색

['블랙핑크', '레드벨벳', '마마무', '에이핑크', '걸스데이', '트와이스'] 배열로 BST를 구성하고, '마마무'를 검색하시오. (Code08-03 + Code08-04)

class TreeNode(): def __init__(self): self.left = None self.data = None self.right = None memory = [] root = None nameAry = ['블랙핑크', '레드벨벳', '마마무', '에이핑크', '걸스데이', '트와이스'] node = TreeNode() node.data = nameAry[0] root = node memory.append(node) for name in nameAry[1:]: node = TreeNode() node.data = name current = root while True: if name < current.data: if current.left == None: current.left = node break current = current.left else: if current.right == None: current.right = node break current = current.right memory.append(node) findName = '마마무' current = root while True: if findName == current.data: print(findName, '을(를) 찾음.') break elif findName < current.data: if current.left == None: print(findName, '이(가) 트리에 없음') break current = current.left else: if current.right == None: print(findName, '이(가) 트리에 없음') break current = current.right
연습문제 2-2 : BST 검색 (확장)

8개 그룹(['블랙핑크', '레드벨벳', '마마무', '에이핑크', '걸스데이', '트와이스', '잇지', '여자친구'])으로 BST를 구성하고, 사용자가 입력한 그룹을 검색하시오. (Self08-02)

class TreeNode(): def __init__(self): self.left = None self.data = None self.right = None memory = [] root = None nameAry = ['블랙핑크', '레드벨벳', '마마무', '에이핑크', '걸스데이', '트와이스', '잇지', '여자친구'] node = TreeNode() node.data = nameAry[0] root = node memory.append(node) for name in nameAry[1:]: node = TreeNode() node.data = name current = root while True: if name < current.data: if current.left == None: current.left = node break current = current.left else: if current.right == None: current.right = node break current = current.right memory.append(node) findName = input('찾을 그룹이름-->') current = root while True: if findName == current.data: print(findName, '을(를) 찾았음.') break elif findName < current.data: if current.left == None: print(findName, '이(가) 트리에 없음') break current = current.left else: if current.right == None: print(findName, '이(가) 트리에 없음') break current = current.right
English
Practice 2-1 : BST Build & Search

Build a BST from ['블랙핑크', '레드벨벳', '마마무', '에이핑크', '걸스데이', '트와이스'] and search for '마마무'. (Code08-03 + Code08-04)

class TreeNode(): def __init__(self): self.left = None self.data = None self.right = None memory = [] root = None nameAry = ['블랙핑크', '레드벨벳', '마마무', '에이핑크', '걸스데이', '트와이스'] node = TreeNode() node.data = nameAry[0] root = node memory.append(node) for name in nameAry[1:]: node = TreeNode() node.data = name current = root while True: if name < current.data: if current.left == None: current.left = node break current = current.left else: if current.right == None: current.right = node break current = current.right memory.append(node) findName = '마마무' current = root while True: if findName == current.data: print(findName, '을(를) 찾음.') break elif findName < current.data: if current.left == None: print(findName, '이(가) 트리에 없음') break current = current.left else: if current.right == None: print(findName, '이(가) 트리에 없음') break current = current.right

Output

마마무 을(를) 찾음.
Practice 2-2 : BST Search (Extended)

Build a BST with 8 groups (adding '잇지', '여자친구') and search for a user-input group name. (Self08-02)

class TreeNode(): def __init__(self): self.left = None self.data = None self.right = None memory = [] root = None nameAry = ['블랙핑크', '레드벨벳', '마마무', '에이핑크', '걸스데이', '트와이스', '잇지', '여자친구'] node = TreeNode() node.data = nameAry[0] root = node memory.append(node) for name in nameAry[1:]: node = TreeNode() node.data = name current = root while True: if name < current.data: if current.left == None: current.left = node break current = current.left else: if current.right == None: current.right = node break current = current.right memory.append(node) findName = input('찾을 그룹이름-->') current = root while True: if findName == current.data: print(findName, '을(를) 찾았음.') break elif findName < current.data: if current.left == None: print(findName, '이(가) 트리에 없음') break current = current.left else: if current.right == None: print(findName, '이(가) 트리에 없음') break current = current.right

Sample Run

찾을 그룹이름--> 잇지
잇지 을(를) 찾았음.
03
Part 3
이진 탐색 트리 응용
BST Applications
도서 검색, 판매 물건 중복 제거, 중복 파일 찾기를 실습합니다.

응용: 도서관 검색 시스템

Application: Library Search System
한국어

책 이름 & 작가 이름 이중 트리 (Code08-06)

도서관에 새로 입고된 책 정보를 두 개의 BST로 관리합니다. 책 이름 트리와 작가 이름 트리를 따로 구성하여 두 가지 방식으로 검색할 수 있습니다.

import random class TreeNode(): def __init__(self): self.left = None self.data = None self.right = None memory = [] rootBook, rootAuth = None, None bookAry = [ ['어린왕자','쌩떽쥐베리'], ['이방인','까뮈'], ['부활','톨스토이'], ['신곡','단테'], ['돈키호테','세브반테스'], ['동물농장','조지오웰'], ['데미안','헤르만헤세'], ['파우스트','괴테'], ['대지','펄벅'] ] random.shuffle(bookAry) ### 책 이름 트리 구성 ### node = TreeNode() node.data = bookAry[0][0] rootBook = node memory.append(node) for book in bookAry[1:]: name = book[0] node = TreeNode() node.data = name current = rootBook while True: if name < current.data: if current.left == None: current.left = node; break current = current.left else: if current.right == None: current.right = node; break current = current.right memory.append(node) ### 작가 이름 트리도 동일하게 구성 ### # (rootAuth, book[1] 사용)
English

Dual BST: Book Title & Author

A library manages books with two separate BSTs: one indexed by book title, another by author name. Users choose which to search.

Design Concept

  • rootBook → BST sorted by book title (book[0])
  • rootAuth → BST sorted by author name (book[1])
  • Same insertion logic, different data source
User Interface

The program asks: "Book search (1) or Author search (2)?" then searches the appropriate tree.

random.shuffle()

The book array is shuffled before building the trees. This creates different tree shapes each run, but the search still works correctly — that's the power of BST!

도서관 검색 코드 완성

Library Search Code Complete
한국어

검색 부분 코드

## 검색 ## bookOrAuth = int(input( '책검색(1), 작가검색(2)-->')) findName = input( '검색할 책 또는 작가-->') if bookOrAuth == 1: root = rootBook else: root = rootAuth current = root while True: if findName == current.data: print(findName, '을(를) 찾음.') break elif findName < current.data: if current.left == None: print(findName, '이(가) 목록에 없음') break current = current.left else: if current.right == None: print(findName, '이(가) 목록에 없음') break current = current.right

실행 결과

책검색(1), 작가검색(2)--> 1
검색할 책 또는 작가--> 어린왕자
어린왕자 을(를) 찾음.

책검색(1), 작가검색(2)--> 2
검색할 책 또는 작가--> 괴테
괴테 을(를) 찾음.
English

Search Section Code

Key Technique

The variable root is set to either rootBook or rootAuth based on the user's choice. The rest of the search code is identical — only the starting tree differs!

Code Pattern Reuse

The BST search algorithm is the same regardless of what data is stored. Build the tree once, search many times — this is the BST's main advantage.

Sample Run

Book(1), Author(2)--> 1
Search--> 어린왕자
어린왕자 found.

Book(1), Author(2)--> 2
Search--> 괴테
괴테 found.

응용: 판매 물건 중복 제거

Application: Remove Duplicate Sales
한국어

편의점 판매 목록 (Ex08-01)

하루 동안 판매된 물건 20개(중복 포함)에서 BST를 이용해 중복 없는 판매 종류를 출력합니다.

핵심 아이디어

BST에 삽입할 때 이미 같은 데이터가 있으면 삽입하지 않고 건너뜁니다. 이렇게 하면 자동으로 중복이 제거됩니다!

import random ## 데이터 준비 ## dataAry = ['바나나맛우유', '레쓰비캔커피', '츄파춥스', '도시락', '삼다수', '코카콜라', '삼각김밥'] sellAry = [random.choice(dataAry) for _ in range(20)] ## BST 삽입 (중복 시 건너뛰기) ## for name in sellAry[1:]: node = TreeNode() node.data = name current = root while True: if name == current.data: break # 중복! 건너뛰기 if name < current.data: if current.left == None: current.left = node memory.append(node) break current = current.left else: if current.right == None: current.right = node memory.append(node) break current = current.right
English

Convenience Store Sales (Ex08-01)

20 items sold today (with duplicates). Use a BST to output only unique item types.

Modified Insertion

The key change: add if name == current.data: break at the top of the while loop. When a duplicate is found, simply skip it — don't insert.

Preorder for Output

After building the BST (duplicates removed), use preorder traversal to print all unique items.

Sample Output

오늘 판매된 물건(중복O) --> [20 items...]
이진 탐색 트리 구성 완료!
오늘 판매된 종류(중복X)--> 바나나맛우유
  도시락 레쓰비캔커피 삼각김밥 삼다수
  코카콜라 츄파춥스

응용: 중복 파일 이름 찾기

Application: Find Duplicate File Names
한국어

폴더 내 중복 파일 검색 (Ex08-02)

특정 폴더와 그 하위 폴더에서 이름이 같은 파일들을 BST를 이용해 찾아냅니다.

import os memory = [] root = None fnameAry = [] ## 폴더에서 파일명 수집 ## folderName = 'C:/Program Files/Common Files/' for dirName, subDirList, fnames \ in os.walk(folderName): for fname in fnames: fnameAry.append(fname) ## BST에 삽입하며 중복 수집 ## node = TreeNode() node.data = fnameAry[0] root = node memory.append(node) dupNameAry = [] for name in fnameAry[1:]: node = TreeNode() node.data = name current = root while True: if name == current.data: dupNameAry.append(name) break if name < current.data: if current.left == None: current.left = node memory.append(node) break current = current.left else: if current.right == None: current.right = node memory.append(node) break current = current.right dupNameAry = list(set(dupNameAry)) print('중복된 파일 목록 -->') print(dupNameAry)
English

Finding Duplicate Files (Ex08-02)

Scan a folder tree and use a BST to detect files with the same name.

1os.walk() collects all filenames recursively
2Insert each name into a BST
3If name == current.data → it's a duplicate! Add to dupNameAry
4Use set() to remove duplicate entries in the result list

Reversed Logic

In the convenience store example, duplicates were skipped. Here, duplicates are collected. The BST insertion loop is the same — only what happens on a match differs!

os.walk()

os.walk(folder) yields (dirName, subDirList, fileNames) for every directory in the tree. It's Python's built-in way to recursively list files.

이진 탐색 트리 vs 리스트 비교

BST vs List Comparison
한국어

성능 비교

연산리스트 (정렬)BST (균형)
검색O(n) 또는 O(log n)O(log n)
삽입O(n)O(log n)
삭제O(n)O(log n)
중복 제거O(n²)O(n log n)

BST의 장점

삽입과 동시에 정렬이 유지됩니다. 별도의 정렬 과정이 필요 없습니다. 검색, 삽입, 삭제 모두 O(log n)으로 효율적입니다.

주의: 편향 트리

데이터가 이미 정렬되어 있으면 편향 트리가 되어 O(n)이 됩니다. 이를 방지하기 위해 AVL 트리, 레드-블랙 트리 같은 균형 트리를 사용합니다.

English

Performance Comparison

OperationSorted ListBalanced BST
SearchO(n) or O(log n)O(log n)
InsertO(n)O(log n)
DeleteO(n)O(log n)
DedupO(n²)O(n log n)

BST Advantage

Data stays sorted as it's inserted — no separate sorting step needed. Search, insert, and delete are all O(log n) for balanced trees.

Warning: Skewed Trees

If data arrives already sorted, the BST degrades to O(n) — essentially a linked list. Self-balancing trees (AVL, Red-Black) prevent this.

연습문제 Part 3

Practice Part 3
한국어
연습문제 3-1 : 편의점 판매 종류 출력

7가지 물건 중 랜덤으로 20개를 판매한 후, BST를 이용해 중복 없는 판매 종류를 전위 순회로 출력하시오. (Ex08-01)

import random class TreeNode(): def __init__(self): self.left = None self.data = None self.right = None memory = [] root = None dataAry = ['바나나맛우유', '레쓰비캔커피', '츄파춥스', '도시락', '삼다수', '코카콜라', '삼각김밥'] sellAry = [random.choice(dataAry) for _ in range(20)] print('오늘 판매된 물건(중복O) -->', sellAry) node = TreeNode() node.data = sellAry[0] root = node memory.append(node) for name in sellAry[1:]: node = TreeNode() node.data = name current = root while True: if name == current.data: break if name < current.data: if current.left == None: current.left = node memory.append(node) break current = current.left else: if current.right == None: current.right = node memory.append(node) break current = current.right print("이진 탐색 트리 구성 완료!") def preorder(node): if node == None: return print(node.data, end=' ') preorder(node.left) preorder(node.right) print('오늘 판매된 종류(중복X)--> ', end=' ') preorder(root)
연습문제 3-2 : 중복 파일 찾기

특정 폴더와 하위 폴더에서 os.walk()로 파일명을 수집한 뒤, BST를 이용해 중복된 파일 이름을 출력하시오. (Ex08-02)

import os class TreeNode(): def __init__(self): self.left = None self.data = None self.right = None memory = [] root = None fnameAry = [] folderName = 'C:/Program Files/Common Files/' for dirName, subDirList, fnames \ in os.walk(folderName): for fname in fnames: fnameAry.append(fname) node = TreeNode() node.data = fnameAry[0] root = node memory.append(node) dupNameAry = [] for name in fnameAry[1:]: node = TreeNode() node.data = name current = root while True: if name == current.data: dupNameAry.append(name) break if name < current.data: if current.left == None: current.left = node memory.append(node) break current = current.left else: if current.right == None: current.right = node memory.append(node) break current = current.right dupNameAry = list(set(dupNameAry)) print(folderName, '및 그 하위 디렉터리의 중복된 파일 목록 -->') print(dupNameAry)
English
Practice 3-1 : Unique Sales Items

From 7 products, randomly sell 20 items. Use a BST to print unique item types via preorder traversal. (Ex08-01)

import random class TreeNode(): def __init__(self): self.left = None self.data = None self.right = None memory = [] root = None dataAry = ['바나나맛우유', '레쓰비캔커피', '츄파춥스', '도시락', '삼다수', '코카콜라', '삼각김밥'] sellAry = [random.choice(dataAry) for _ in range(20)] print('오늘 판매된 물건(중복O) -->', sellAry) node = TreeNode() node.data = sellAry[0] root = node memory.append(node) for name in sellAry[1:]: node = TreeNode() node.data = name current = root while True: if name == current.data: break if name < current.data: if current.left == None: current.left = node memory.append(node) break current = current.left else: if current.right == None: current.right = node memory.append(node) break current = current.right print("이진 탐색 트리 구성 완료!") def preorder(node): if node == None: return print(node.data, end=' ') preorder(node.left) preorder(node.right) print('오늘 판매된 종류(중복X)--> ', end=' ') preorder(root)

Sample Output

오늘 판매된 물건(중복O) --> [20 items...]
이진 탐색 트리 구성 완료!
오늘 판매된 종류(중복X)--> 바나나맛우유
  도시락 레쓰비캔커피 삼각김밥 삼다수
  코카콜라 츄파춥스
Practice 3-2 : Find Duplicate Files

Collect filenames from a folder tree using os.walk(), then use a BST to find and print duplicate file names. (Ex08-02)

import os class TreeNode(): def __init__(self): self.left = None self.data = None self.right = None memory = [] root = None fnameAry = [] folderName = 'C:/Program Files/Common Files/' for dirName, subDirList, fnames \ in os.walk(folderName): for fname in fnames: fnameAry.append(fname) node = TreeNode() node.data = fnameAry[0] root = node memory.append(node) dupNameAry = [] for name in fnameAry[1:]: node = TreeNode() node.data = name current = root while True: if name == current.data: dupNameAry.append(name) break if name < current.data: if current.left == None: current.left = node memory.append(node) break current = current.left else: if current.right == None: current.right = node memory.append(node) break current = current.right dupNameAry = list(set(dupNameAry)) print(folderName, '및 그 하위 디렉터리의 중복된 파일 목록 -->') print(dupNameAry)

Chapter 8 정리

Chapter 8 Summary
한국어

핵심 요약

이진 트리 기본

각 노드가 최대 2개의 자식을 가지는 트리 구조. TreeNode 클래스로 left, data, right 세 필드를 구현합니다.

순회 (Traversal)

전위(루왼오), 중위(왼루오), 후위(왼오루) — print()의 위치만 다릅니다. 모두 재귀로 구현합니다.

이진 탐색 트리 (BST)

왼쪽 < 루트 < 오른쪽 규칙으로 정렬된 이진 트리. 삽입, 검색, 삭제 모두 O(log n)으로 효율적입니다.

BST 응용

중복 제거(편의점 판매), 중복 탐지(파일 검색), 다중 인덱스(도서관 검색) 등 실용적인 활용이 가능합니다.

다음 장 미리보기

Chapter 9에서는 그래프(Graph)를 학습합니다. 트리는 그래프의 특수한 형태입니다!

English

Key Takeaways

Binary Tree Basics

A tree where each node has at most 2 children. TreeNode class implements left, data, right fields.

Traversal

Preorder (Root-L-R), Inorder (L-Root-R), Postorder (L-R-Root) — only the position of print() differs. All use recursion.

Binary Search Tree

A sorted binary tree: left < root < right. Insert, search, delete all run in O(log n) for balanced trees.

BST Applications

Deduplication (store sales), duplicate detection (file search), multi-index search (library) — practical and powerful.

Next Chapter Preview

Chapter 9 covers Graphs. A tree is actually a special case of a graph!

1 / 23