๐Ÿšถโ€โ™‚๏ธRoad to ์ฝ”ํ…Œ(13) - ํŠธ๋ฆฌ

์•ˆํƒœํ˜„ยท2025๋…„ 5์›” 16์ผ

Algorithm

๋ชฉ๋ก ๋ณด๊ธฐ
14/15
post-thumbnail

ํŠธ๋ฆฌ(Tree)์™€ ์ˆœํšŒ(Traversal) ์™„์ „ ์ •๋ฆฌ

ํŠธ๋ฆฌ๋Š” ๊ณ„์ธต์  ๊ตฌ์กฐ๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๋Œ€ํ‘œ์ ์ธ ๋น„์„ ํ˜• ์ž๋ฃŒ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.
์ด ๊ธ€์—์„œ๋Š” ํŠธ๋ฆฌ์˜ ๊ธฐ๋ณธ ๊ฐœ๋…๋ถ€ํ„ฐ BFS/DFS ์ˆœํšŒ ๋ฐฉ๋ฒ•๊นŒ์ง€ ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


ํŠธ๋ฆฌ(Tree)์˜ ์ •์˜

ํŠธ๋ฆฌ๋Š” ๋…ธ๋“œ(Node)์™€ ๊ฐ„์„ (Edge)์œผ๋กœ ๊ตฌ์„ฑ๋œ ๊ณ„์ธต์  ์ž๋ฃŒ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.

  • ๋ฃจํŠธ ๋…ธ๋“œ(Root): ์ตœ์ƒ์œ„ ๋…ธ๋“œ (๋ถ€๋ชจ๊ฐ€ ์—†์Œ)
  • ๋ถ€๋ชจ-์ž์‹ ๊ด€๊ณ„: ์ƒํ•˜ ์—ฐ๊ฒฐ ๊ตฌ์กฐ
  • ์„œ๋ธŒํŠธ๋ฆฌ(Subtree): ํŠธ๋ฆฌ ๋‚ด๋ถ€์— ํฌํ•จ๋œ ์ž‘์€ ํŠธ๋ฆฌ

๐ŸŒณ ํŠธ๋ฆฌ๋Š” ๋ฐฉํ–ฅ์„ฑ ๋น„์ˆœํ™˜ ๊ทธ๋ž˜ํ”„(DAG)์˜ ์ผ์ข…์ž…๋‹ˆ๋‹ค.
๊ฐ„์„  ์ˆ˜ = ๋…ธ๋“œ ์ˆ˜ - 1, ์ˆœํ™˜ ๊ตฌ์กฐ๊ฐ€ ์—†๋‹ค๋Š” ํŠน์ง•์ด ์žˆ์Šต๋‹ˆ๋‹ค.


ํŠธ๋ฆฌ ๊ด€๋ จ ํ•ต์‹ฌ ๊ฐœ๋…

์šฉ์–ด์„ค๋ช…์˜ˆ์‹œ
๋…ธ๋“œ(Node)ํŠธ๋ฆฌ์˜ ๊ฐ ์š”์†Œ (๋ฐ์ดํ„ฐ + ํฌ์ธํ„ฐ)A, B, C ...
๊ฐ„์„ (Edge)๋…ธ๋“œ ๊ฐ„ ์—ฐ๊ฒฐ ์„ A-B, B-C
๋ฃจํŠธ(Root)์ตœ์ƒ์œ„ ๋…ธ๋“œํŠธ๋ฆฌ์˜ ์‹œ์ž‘์ 
๋ฆฌํ”„(Leaf)์ž์‹์ด ์—†๋Š” ์ตœํ•˜์œ„ ๋…ธ๋“œํŠธ๋ฆฌ์˜ ๋ ๋…ธ๋“œ
์ฐจ์ˆ˜(Degree)ํ•œ ๋…ธ๋“œ๊ฐ€ ๊ฐ€์ง„ ์ž์‹ ์ˆ˜2์ง„ ํŠธ๋ฆฌ: ์ตœ๋Œ€ ์ฐจ์ˆ˜ 2
๋ ˆ๋ฒจ(Level)๋ฃจํŠธ(0)๋ถ€ํ„ฐ์˜ ๊นŠ์ด๋ ˆ๋ฒจ 0 โ†’ ๋ฃจํŠธ
๋†’์ด(Height)๋ฃจํŠธ์—์„œ ๊ฐ€์žฅ ๋จผ ๋ฆฌํ”„๊นŒ์ง€์˜ ๊ฑฐ๋ฆฌํŠธ๋ฆฌ์˜ ์ตœ๋Œ€ ๊นŠ์ด

ํŠธ๋ฆฌ ์ˆœํšŒ(Traversal) ๋ฐฉ๋ฒ•

ํŠธ๋ฆฌ ์ˆœํšŒ๋Š” ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ์ฒด๊ณ„์ ์œผ๋กœ ๋ฐฉ๋ฌธํ•˜๋Š” ๊ธฐ์ˆ ์ž…๋‹ˆ๋‹ค.
์ฃผ์š” ๋ฐฉ๋ฒ•์œผ๋กœ BFS(Level-order)์™€ DFS(Pre/In/Post-order)๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.


1. BFS (Level-order)

๋ ˆ๋ฒจ๋ณ„๋กœ ์ขŒโ†’์šฐ ๋ฐฉ๋ฌธํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
ํ(Queue)๋ฅผ ์‚ฌ์šฉํ•ด ๊ตฌํ˜„ํ•˜๋ฉฐ, ์ตœ๋‹จ ๊ฒฝ๋กœ ํƒ์ƒ‰์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

![Level-order ์˜ˆ์‹œ](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/66563d83-ecb0-4182-bdc1-f9cc308895d0/Tree_3._level_orderOrder(Node root) {
if (root == null) return;

Queue q = new ArrayDeque<>();
q.add(root);

while (!q.isEmpty()) {
    Node cur = q.poll();
    System.out.print(cur.value + " ");

    for (Node child : cur.children) {
        q.add(child);
    }
}

}


**์‹คํ–‰ ๊ฒฐ๊ณผ**: A โ†’ B โ†’ C โ†’ D โ†’ E โ†’ F โ†’ G โ†’ H โ†’ I โ†’ J โ†’ K โ†’ L  
**์‹œ๊ฐ„ ๋ณต์žก๋„**: O(N) (๋ชจ๋“  ๋…ธ๋“œ ํ•œ ๋ฒˆ์”ฉ ๋ฐฉ๋ฌธ)

---

### 2. DFS (Depth First Search)

ํ•œ ๊ฒฝ๋กœ๋ฅผ ๋๊นŒ์ง€ ํƒ์ƒ‰ ํ›„ ๋Œ์•„์™€ ๋‹ค๋ฅธ ๊ฒฝ๋กœ๋ฅผ ํƒ์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.  
**์žฌ๊ท€** ๋˜๋Š” **์Šคํƒ**์œผ๋กœ ๊ตฌํ˜„ํ•˜๋ฉฐ, **์ „์œ„/์ค‘์œ„/ํ›„์œ„** ์„ธ ๊ฐ€์ง€ ๋ฐฉ์‹์ด ์žˆ์Šต๋‹ˆ๋‹ค.

#### (1) ์ „์œ„ ์ˆœํšŒ (Pre-order)

**๋…ธ๋“œ โ†’ ์™ผ์ชฝ โ†’ ์˜ค๋ฅธ์ชฝ** ์ˆœ์„œ๋กœ ๋ฐฉ๋ฌธํ•ฉ๋‹ˆ๋‹ค.  
ํŠธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋ณต์ œํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

```java
void preOrder(Node root) {
    if (root == null) return;
    
    System.out.print(root.value + " "); // ํ˜„์žฌ ๋…ธ๋“œ
    preOrder(root.left);  // ์™ผ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ
    preOrder(root.right); // ์˜ค๋ฅธ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ
}

์‹คํ–‰ ๊ฒฐ๊ณผ: A โ†’ B โ†’ E โ†’ F โ†’ C โ†’ G โ†’ H โ†’ D โ†’ I โ†’ J โ†’ K โ†’ L

(2) ์ค‘์œ„ ์ˆœํšŒ (In-order)

์™ผ์ชฝ โ†’ ๋…ธ๋“œ โ†’ ์˜ค๋ฅธ์ชฝ ์ˆœ์„œ๋กœ ๋ฐฉ๋ฌธํ•ฉ๋‹ˆ๋‹ค.
์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ(BST)์—์„œ ๊ฐ’ ์ •๋ ฌ ์‹œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

void inOrder(Node root) {
    if (root == null) return;
    
    inOrder(root.left);   // ์™ผ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ
    System.out.print(root.value + " "); // ํ˜„์žฌ ๋…ธ๋“œ
    inOrder(root.right);  // ์˜ค๋ฅธ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ
}

์‹คํ–‰ ๊ฒฐ๊ณผ: E โ†’ B โ†’ F โ†’ A โ†’ G โ†’ C โ†’ H โ†’ D โ†’ J โ†’ I โ†’ K โ†’ L

(3) ํ›„์œ„ ์ˆœํšŒ (Post-order)

์™ผ์ชฝ โ†’ ์˜ค๋ฅธ์ชฝ โ†’ ๋…ธ๋“œ ์ˆœ์„œ๋กœ ๋ฐฉ๋ฌธํ•ฉ๋‹ˆ๋‹ค.
ํŠธ๋ฆฌ ์‚ญ์ œ ์ž‘์—… ์‹œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

void postOrder(Node root) {
    if (root == null) return;
    
    postOrder(root.left);  // ์™ผ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ
    postOrder(root.right); // ์˜ค๋ฅธ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ
    System.out.print(root.value + " "); // ํ˜„์žฌ ๋…ธ๋“œ
}

์‹คํ–‰ ๊ฒฐ๊ณผ: E โ†’ F โ†’ B โ†’ G โ†’ H โ†’ C โ†’ J โ†’ K โ†’ L โ†’ I โ†’ D โ†’ A

์‹œ๊ฐ„ ๋ณต์žก๋„: ์„ธ ๋ฐฉ์‹ ๋ชจ๋‘ O(N) (๊ฐ ๋…ธ๋“œ ํ•œ ๋ฒˆ์”ฉ ๋ฐฉ๋ฌธ)


๋งˆ๋ฌด๋ฆฌ

ํŠธ๋ฆฌ ์ˆœํšŒ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ ํ•ด๊ฒฐ์˜ ๊ธฐ์ดˆ์ž…๋‹ˆ๋‹ค.

  • BFS: ๋ ˆ๋ฒจ๋ณ„ ํƒ์ƒ‰, ์ตœ๋‹จ ๊ฒฝ๋กœ
  • DFS: ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰, ๊ตฌ์กฐ ๋ถ„์„

๋ฌธ์ œ ์œ ํ˜•์— ๋งž์ถฐ ์ ์ ˆํ•œ ์ˆœํšŒ ๋ฐฉ์‹์„ ์„ ํƒํ•ด๋ณด์„ธ์š”!
๊ถ๊ธˆํ•œ ์ ์ด๋‚˜ ๋ณด์™„ํ•  ๋‚ด์šฉ์ด ์žˆ๋‹ค๋ฉด ๋Œ“๊ธ€๋กœ ๋‚จ๊ฒจ์ฃผ์„ธ์š” ๐Ÿ˜Š


velog์— ๋ณต์‚ฌํ•˜์—ฌ ๋ฐ”๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
์ถ”๊ฐ€ ์„ค๋ช…์ด๋‚˜ ์˜ˆ์‹œ๊ฐ€ ํ•„์š”ํ•˜๋ฉด ์–ธ์ œ๋“  ์š”์ฒญํ•ด ์ฃผ์„ธ์š”!

ํŠธ๋ฆฌ(Tree) ๊ตฌํ˜„ ๋ฐฉ์‹ ์ •๋ฆฌ

ํŠธ๋ฆฌ๋Š” ๋…ธ๋“œ์™€ ๊ฐ„์„ ์œผ๋กœ ๊ตฌ์„ฑ๋œ ๊ณ„์ธต์  ์ž๋ฃŒ๊ตฌ์กฐ๋กœ, ๋‹ค์–‘ํ•œ ๊ตฌํ˜„ ๋ฐฉ์‹์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” ์‹ค์ „ ์ฝ”๋”ฉํ…Œ์ŠคํŠธ์™€ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ์—์„œ ์ž์ฃผ ๋“ฑ์žฅํ•˜๋Š” ํŠธ๋ฆฌ ๊ตฌํ˜„ ํŒจํ„ด๋“ค์„ ํ•œ๋ˆˆ์— ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.


1. ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ (Adjacency List)

ํŠธ๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.
ํŠธ๋ฆฌ๋Š” ๊ทธ๋ž˜ํ”„์˜ ์ผ์ข…์ด๋ฏ€๋กœ, ๊ทธ๋ž˜ํ”„์—์„œ ๋„๋ฆฌ ์“ฐ์ด๋Š” ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ ๋ฐฉ์‹์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ํŠธ๋ฆฌ๋Š” ๋ถ€๋ชจ-์ž์‹ ๊ด€๊ณ„๊ฐ€ ๋ช…ํ™•ํ•˜๊ณ  ๋ฐฉํ–ฅ์„ฑ์ด ์žˆ์œผ๋ฏ€๋กœ ๋‹จ๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„๋กœ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

์ธ์ ‘ ๋ฆฌ์ŠคํŠธ ๊ตฌํ˜„ ๋ฐฉ์‹

๋ฐฉ์‹์ž๋ฃŒํ˜•ํŠน์ง•
2์ฐจ์› ๋ฐฐ์—ดint[][]์ž…๋ ฅ์ด ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ์ฃผ์–ด์งˆ ๋•Œ ์‚ฌ์šฉ, ์ •์  ๊ตฌ์กฐ
2์ฐจ์› ๋ฆฌ์ŠคํŠธList>๋…ธ๋“œ ๋ฒˆํ˜ธ๊ฐ€ ์—ฐ์†์ ์ผ ๋•Œ, edge ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ง์ ‘ ๊ตฌ์„ฑ
ํ•ด์‹œ๋งตMap>๋…ธ๋“œ ๋ฒˆํ˜ธ๊ฐ€ ๋ถˆ์—ฐ์†์ ์ด๊ฑฐ๋‚˜ ๋ฌธ์ž์—ด์ผ ๋•Œ ์ ํ•ฉ

(1) 2์ฐจ์› ๋ฐฐ์—ด

int[][] tree = {
    {1, 2},    // 0๋ฒˆ ๋…ธ๋“œ์˜ ์ž์‹
    {},        // 1๋ฒˆ ๋…ธ๋“œ์˜ ์ž์‹
    {3, 4},    // 2๋ฒˆ ๋…ธ๋“œ์˜ ์ž์‹
    {},        // 3๋ฒˆ ๋…ธ๋“œ์˜ ์ž์‹
    {}         // 4๋ฒˆ ๋…ธ๋“œ์˜ ์ž์‹
};

์ž์‹ ๋…ธ๋“œ ์ˆœํšŒ:

for (int child : tree[0]) {
    System.out.println(child);   // 1, 2
}

(2) 2์ฐจ์› ๋ฆฌ์ŠคํŠธ

int n = 5;
List> tree = new ArrayList<>();
for (int i = 0; i ());
tree.get(0).add(1);
tree.get(0).add(2);
tree.get(2).add(3);
tree.get(2).add(4);

์ž์‹ ๋…ธ๋“œ ์ˆœํšŒ:

for (int child : tree.get(0)) {
    System.out.println(child);   // 1, 2
}

(3) ํ•ด์‹œ๋งต

Map> tree = new HashMap<>();
tree.putIfAbsent(0, new ArrayList<>());
tree.get(0).add(1);
tree.get(0).add(2);
tree.putIfAbsent(2, new ArrayList<>());
tree.get(2).add(3);
tree.get(2).add(4);

์ž์‹ ๋…ธ๋“œ ์ˆœํšŒ:

for (int child : tree.get(0)) {
    System.out.println(child);  // 1, 2
}

2. ๊ฐ„์„  ๋ฆฌ์ŠคํŠธ (Edge List)

ํŠธ๋ฆฌ์˜ ๊ฐ ๊ฐ„์„ ์„ ๋ถ€๋ชจ-์ž์‹ ์Œ์œผ๋กœ ์ €์žฅํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
๋ฌธ์ œ์˜ ์ž…๋ ฅ์ด ๊ฐ„์„  ๋ฆฌ์ŠคํŠธ ํ˜•ํƒœ์ผ ๋•Œ๊ฐ€ ๋งŽ์œผ๋ฉฐ, ๋ณดํ†ต ๊ฐ„์„  ๋ฆฌ์ŠคํŠธ โ†’ ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ๋กœ ๋ณ€ํ™˜ํ•ด์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

int[][] edges = {
    {0, 1},
    {0, 2},
    {2, 3},
    {2, 4}
};

(1) ๊ฐ„์„  ๋ฆฌ์ŠคํŠธ โ†’ ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ(2์ฐจ์› ๋ฆฌ์ŠคํŠธ)

List> tree = new ArrayList<>();
for (int i = 0; i ());
for (int[] edge : edges) {
    int parent = edge[0], child = edge[1];
    tree.get(parent).add(child);
}

(2) ๊ฐ„์„  ๋ฆฌ์ŠคํŠธ โ†’ ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ(ํ•ด์‹œ๋งต)

Map> tree = new HashMap<>();
for (int[] edge : edges) {
    int parent = edge[0], child = edge[1];
    tree.putIfAbsent(parent, new ArrayList<>());
    tree.get(parent).add(child);
}

์ฃผ์˜: ํ•ด์‹œ๋งต ๊ธฐ๋ฐ˜ ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ๋Š” ์ž์‹์ด ์—†๋Š” ๋…ธ๋“œ๊ฐ€ Map์— ํฌํ•จ๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ํƒ์ƒ‰ ์‹œ containsKey() ๋˜๋Š” getOrDefault()๋ฅผ ํ™œ์šฉํ•ด ์•ˆ์ „ํ•˜๊ฒŒ ์ˆœํšŒํ•˜์„ธ์š”.

for (int child : tree.getOrDefault(1, Collections.emptyList())) {
    // ์•ˆ์ „ํ•˜๊ฒŒ ์ˆœํšŒ
}

3. ํด๋ž˜์Šค ๊ธฐ๋ฐ˜ ์ด์ง„ ํŠธ๋ฆฌ (Binary Tree)

๊ฐ ๋…ธ๋“œ๊ฐ€ ์ตœ๋Œ€ ๋‘ ๊ฐœ์˜ ์ž์‹๋งŒ ๊ฐ€์ง€๋Š” ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.
ํด๋ž˜์Šค ๊ธฐ๋ฐ˜ ํŠธ๋ฆฌ ๊ตฌํ˜„์€ Leetcode ๋“ฑ์—์„œ ๊ฐ€์žฅ ํ”ํ•˜๊ฒŒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

์ž์‹ ๋…ธ๋“œ ์ ‘๊ทผ:

System.out.println(root.left);
System.out.println(root.right);

4. ํด๋ž˜์Šค ๊ธฐ๋ฐ˜ ์ผ๋ฐ˜ ํŠธ๋ฆฌ (N-ary Tree)

์ž์‹์˜ ์ˆ˜๊ฐ€ ์ •ํ•ด์ ธ ์žˆ์ง€ ์•Š์€ ํŠธ๋ฆฌ ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.
๊ฐ ๋…ธ๋“œ๊ฐ€ ์ž์‹ ๋…ธ๋“œ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ง์ ‘ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

class Node {
    int val;
    List children;
    Node() {}
    Node(int val) { this.val = val; }
    Node(int val, List children) {
        this.val = val;
        this.children = children;
    }
}

์ž์‹ ๋…ธ๋“œ ์ˆœํšŒ:

for (Node child : root.children) {
    System.out.println(child.val);
}

5. ๋ ˆ๋ฒจ ์ˆœ์„œ ๋ฐฐ์—ด (์™„์ „ ์ด์ง„ ํŠธ๋ฆฌ, ํž™)

์™„์ „ ์ด์ง„ ํŠธ๋ฆฌ์—์„œ๋Š” ๋…ธ๋“œ๋ฅผ ๋ ˆ๋ฒจ ์ˆœ์„œ๋Œ€๋กœ ๋ฐฐ์—ด์— ์ €์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.

int[] tree = {0, 1, 2, -1, -1, 3, 4}; // -1์€ ๋นˆ ์ž๋ฆฌ
  • ๋ถ€๋ชจ ์ธ๋ฑ์Šค: i
    • ์™ผ์ชฝ ์ž์‹: 2 * i + 1
    • ์˜ค๋ฅธ์ชฝ ์ž์‹: 2 * i + 2
  • ์ž์‹ ์ธ๋ฑ์Šค: j
    • ๋ถ€๋ชจ: (j - 1) // 2

6. ๋ฐฐ์—ด ๊ธฐ๋ฐ˜ ์ž์‹ ์ •๋ณด (ํŠน์ • ๋ฌธ์ œํ˜•)

๊ฐ ๋…ธ๋“œ์˜ ์ž์‹ ์ •๋ณด๋ฅผ ๋ฐฐ์—ด๋กœ ์ฃผ๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

int[][] links = {
    {-1, -1},  // 0๋ฒˆ ๋…ธ๋“œ์˜ ์ž์‹ ์—†์Œ
    {-1, -1},  // 1๋ฒˆ ๋…ธ๋“œ์˜ ์ž์‹ ์—†์Œ
    {-1, 0},   // 2๋ฒˆ ๋…ธ๋“œ์˜ ์˜ค๋ฅธ์ชฝ ์ž์‹์ด 0๋ฒˆ
    {2, 1}     // 3๋ฒˆ ๋…ธ๋“œ์˜ ์™ผ์ชฝ ์ž์‹์ด 2๋ฒˆ, ์˜ค๋ฅธ์ชฝ ์ž์‹์ด 1๋ฒˆ
};
  • links[i]๋Š” i๋ฒˆ ๋…ธ๋“œ์˜ [์™ผ์ชฝ ์ž์‹, ์˜ค๋ฅธ์ชฝ ์ž์‹] ์ •๋ณด
  • ์ž์‹์ด ์—†์œผ๋ฉด -1

๋งˆ๋ฌด๋ฆฌ

ํŠธ๋ฆฌ๋Š” ๋ฌธ์ œ์˜ ์ž…๋ ฅ ํ˜•ํƒœ์— ๋”ฐ๋ผ ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ: ๊ฐ€์žฅ ๋ฒ”์šฉ์ , ๊ทธ๋ž˜ํ”„/ํŠธ๋ฆฌ ๋ชจ๋‘ ์‚ฌ์šฉ
  • ๊ฐ„์„  ๋ฆฌ์ŠคํŠธ: ์ž…๋ ฅ์ด edge list์ผ ๋•Œ
  • ํด๋ž˜์Šค ๊ธฐ๋ฐ˜: ์ด์ง„ ํŠธ๋ฆฌ, N-ary ํŠธ๋ฆฌ ๋“ฑ ๊ฐ์ฒด์ง€ํ–ฅ์  ๊ตฌํ˜„
  • ๋ฐฐ์—ด/๋ ˆ๋ฒจ ์ˆœ์„œ: ์™„์ „ ์ด์ง„ ํŠธ๋ฆฌ, ํž™ ๋“ฑ

๋ฌธ์ œ์— ๋”ฐ๋ผ ์ ํ•ฉํ•œ ๊ตฌํ˜„ ๋ฐฉ์‹์„ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.


ํŠธ๋ฆฌ์™€ ์žฌ๊ท€

ํŠธ๋ฆฌ๋Š” ๊ณ„์ธต์  ๊ตฌ์กฐ์™€ ์žฌ๊ท€์  ์ •์˜๊ฐ€ ํ•ต์‹ฌ์ธ ์ž๋ฃŒ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค. ํŠธ๋ฆฌ์˜ ๋ณธ์งˆ, ์žฌ๊ท€์  ํƒ์ƒ‰ ์›๋ฆฌ, ๋‹ค์–‘ํ•œ ๊ตฌํ˜„ ๋ฐ ํƒ์ƒ‰ ํŒจํ„ด์„ ์˜ˆ์ œ ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค.


1. ํŠธ๋ฆฌ์˜ ์žฌ๊ท€์  ์ •์˜

ํŠธ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์žฌ๊ท€์ ์œผ๋กœ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ๋นˆ ํŠธ๋ฆฌ(Empty Tree)๋„ ํŠธ๋ฆฌ์ด๋‹ค.
  2. ๋…ธ๋“œ๊ฐ€ ํ•˜๋‚˜๋งŒ ์žˆ๋Š” ํŠธ๋ฆฌ(๋ฃจํŠธ๋งŒ ์กด์žฌ)๋„ ํŠธ๋ฆฌ์ด๋‹ค.
  3. ๋ฃจํŠธ ๋…ธ๋“œ + 0๊ฐœ ์ด์ƒ์˜ ์ž์‹ ํŠธ๋ฆฌ๊ฐ€ ๋ชจ์ด๋ฉด ์ „์ฒด๋กœ ํ•˜๋‚˜์˜ ํŠธ๋ฆฌ์ด๋‹ค.

์ฆ‰, ํŠธ๋ฆฌ๋Š” โ€œ์–ด๋–ค ๋…ธ๋“œ + ๊ทธ ๋…ธ๋“œ์˜ ์„œ๋ธŒํŠธ๋ฆฌ๋“ค(subtrees)โ€๋กœ ์™„์„ฑ๋˜๋Š” ๊ณ„์ธต ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.

์„œ๋ธŒํŠธ๋ฆฌ(Subtree)๋ž€?

ํŠธ๋ฆฌ์—์„œ ์ž„์˜์˜ ๋…ธ๋“œ๋ฅผ ๋ฃจํŠธ๋กœ ์žก๊ณ , ๊ทธ ํ•˜์œ„ ๋…ธ๋“œ๋“ค์„ ๋ชจ๋‘ ํฌํ•จํ•œ ๋ถ€๋ถ„ ๊ตฌ์กฐ๋ฅผ ์„œ๋ธŒํŠธ๋ฆฌ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
ํŠธ๋ฆฌ๋Š” "ํŠธ๋ฆฌ ์•ˆ์— ๋˜ ํŠธ๋ฆฌ"๊ฐ€ ๋“ค์–ด์žˆ๋Š” ์žฌ๊ท€ ๊ตฌ์กฐ์ด๊ธฐ ๋•Œ๋ฌธ์—, ํŠธ๋ฆฌ ๋ฌธ์ œ๋ฅผ ํ’€ ๋•Œ ์„œ๋ธŒํŠธ๋ฆฌ ๊ฐœ๋…์ด ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ:

    A
   / \
  B   C
 / \
D   E
  • B๋ฅผ ๋ฃจํŠธ๋กœ ๋ณด๋ฉด, B-D-E๊ฐ€ ํ•˜๋‚˜์˜ ์„œ๋ธŒํŠธ๋ฆฌ์ž…๋‹ˆ๋‹ค.

2. ํŠธ๋ฆฌ์™€ ์žฌ๊ท€์  ํƒ์ƒ‰

ํŠธ๋ฆฌ๋Š” ๋ถ€๋ชจ๊ฐ€ ํ•˜๋Š” ์ผ์„ ์ž์‹๋„ ๋ฐ˜๋ณตํ•œ๋‹ค๋Š” ํŠน์„ฑ ๋•Œ๋ฌธ์—, ์žฌ๊ท€์  ์ ‘๊ทผ์ด ๋งค์šฐ ์ž์—ฐ์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค.

  • ํŠธ๋ฆฌ์˜ ๋ชจ๋“  ๋…ธ๋“œ ๊ฐ’์„ ์ถœ๋ ฅํ•˜๋ ค๋ฉด?
    โ†’ ๋ถ€๋ชจ ๋…ธ๋“œ ๊ฐ’์„ ์ถœ๋ ฅํ•˜๊ณ , ์ž์‹ ๋…ธ๋“œ๋“ค์„ ์žฌ๊ท€ ํ˜ธ์ถœ๋กœ ํƒ์ƒ‰

  • ํŠธ๋ฆฌ์—์„œ ํŠน์ • ๊ฐ’์„ ๊ณ„์‚ฐํ•˜๋ ค๋ฉด?
    โ†’ ์ž์‹ ๋…ธ๋“œ๋“ค์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ชจ์•„ ์ตœ์ข… ๊ฒฐ๋ก  ๋„์ถœ

์žฌ๊ท€์  ์ ‘๊ทผ๋ฒ•์˜ ํ•ต์‹ฌ

  • ์„œ๋ธŒํŠธ๋ฆฌ ๋‹จ์œ„๋กœ ๋ฌธ์ œ๋ฅผ ๋‚˜๋ˆ„๊ธฐ
  • ๋ถ€๋ชจ๊ฐ€ ํ•˜๋Š” ์ผ์„ ์ž์‹๋„ ๋ฐ˜๋ณตํ•œ๋‹ค๊ณ  ๊ฐ€์ •
  • ์žฌ๊ท€ ํ•จ์ˆ˜๋กœ ์ž์‹ ๋…ธ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ํŠธ๋ฆฌ๋ฅผ ์ˆœํšŒ

3. ํŠธ๋ฆฌ ํƒ์ƒ‰ โ€“ ์ฝ”๋“œ ํ…œํ”Œ๋ฆฟ

(1) ์ผ๋ฐ˜ ํŠธ๋ฆฌ(์ž์‹ ๋ฆฌ์ŠคํŠธ) โ€“ DFS

void dfs(Node node) {
    // ํ˜„์žฌ ๋…ธ๋“œ ์ฒ˜๋ฆฌ
    System.out.println(node.value);
    for (Node child : node.children) {
        dfs(child);
    }
}

์˜ˆ์ œ

class Node {
    int value;
    List children = new ArrayList<>();
    Node(int value) { this.value = value; }
}

public class TreeDFS {
    public static void dfs(Node node) {
        System.out.println(node.value);
        for (Node child : node.children) {
            dfs(child);
        }
    }
    public static void main(String[] args) {
        Node root = new Node(1);
        Node child1 = new Node(2);
        Node child2 = new Node(3);
        Node child3 = new Node(4);
        Node child4 = new Node(5);
        root.children.add(child1);
        root.children.add(child2);
        child1.children.add(child3);
        child1.children.add(child4);
        dfs(root);
    }
}

(2) ์ด์ง„ ํŠธ๋ฆฌ โ€“ DFS

void dfs(Node node) {
    if (node == null) return;
    System.out.println(node.value);
    dfs(node.left);
    dfs(node.right);
}

์˜ˆ์ œ

class Node {
    int value;
    Node left, right;
    Node(int value) { this.value = value; }
}

public class BinaryTreeDFS {
    public static void dfs(Node node) {
        if (node == null) return;
        System.out.println(node.value);
        dfs(node.left);
        dfs(node.right);
    }
    public static void main(String[] args) {
        Node root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);
        dfs(root);
    }
}

(3) ๋ฌด๋ฐฉํ–ฅ ํŠธ๋ฆฌ(์–‘๋ฐฉํ–ฅ ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ)

Map> tree = new HashMap<>() {{
    put(1, List.of(2, 3));
    put(2, List.of(1, 4, 5));
    put(3, List.of(1));
    put(4, List.of(2));
    put(5, List.of(2));
}};
  • visited ์ง‘ํ•ฉ ์‚ฌ์šฉ: ์ด๋ฏธ ๋ฐฉ๋ฌธํ•œ ๋…ธ๋“œ ์žฌ๋ฐฉ๋ฌธ ๋ฐฉ์ง€
void dfs(int cur, Set visited) {
    System.out.println(cur);
    visited.add(cur);
    for (int nxt : tree.get(cur)) {
        if (!visited.contains(nxt)) {
            dfs(nxt, visited);
        }
    }
}
  • parent ๋ณ€์ˆ˜ ์‚ฌ์šฉ: ๋ถ€๋ชจ๋กœ ๋Œ์•„๊ฐ€๋Š” ์—ญ๋ฐฉํ–ฅ ์ด๋™ ๋ฐฉ์ง€
void dfs(int cur, int parent) {
    System.out.println(cur);
    for (int nxt : tree.get(cur)) {
        if (nxt == parent) continue;
        dfs(nxt, cur);
    }
}

(4) ์ผ๋ฐฉํ–ฅ ํŠธ๋ฆฌ(Directed Tree)

Map> tree = new HashMap<>() {{
    put(1, List.of(2, 3));
    put(2, List.of(4, 5));
    put(3, List.of());
    put(4, List.of());
    put(5, List.of());
}};
  • ๋ฐฉํ–ฅ์„ฑ์ด ์žˆ์œผ๋ฏ€๋กœ visited ์—†์ด ํƒ์ƒ‰ ๊ฐ€๋Šฅ
  • ํ•„์š”ํ•˜๋ฉด visited๋ฅผ ์จ๋„ ๋ฌด๋ฐฉ
void dfs(int cur) {
    System.out.println(cur);
    for (int nxt : tree.get(cur)) {
        dfs(nxt);
    }
}

(5) ๋ฐฐ์—ด ๊ธฐ๋ฐ˜ ํŠธ๋ฆฌ(์™„์ „ ์ด์ง„ ํŠธ๋ฆฌ, ํž™)

  • ๋ฐฐ์—ด ์ธ๋ฑ์Šค ๊ทœ์น™
    • ์™ผ์ชฝ ์ž์‹: 2 * i + 1
    • ์˜ค๋ฅธ์ชฝ ์ž์‹: 2 * i + 2
int[] arr = {1, 2, 3, 4, 5, -1, -1};
void dfs(int index) {
    if (index >= arr.length || arr[index] == -1) return;
    System.out.println(arr[index]);
    dfs(2 * index + 1); // ์™ผ์ชฝ
    dfs(2 * index + 2); // ์˜ค๋ฅธ์ชฝ
}

4. ๋งˆ๋ฌด๋ฆฌ

  • ํŠธ๋ฆฌ๋Š” ์žฌ๊ท€์  ์ •์˜์™€ ์„œ๋ธŒํŠธ๋ฆฌ ๊ฐœ๋…์ด ํ•ต์‹ฌ
  • DFS ์žฌ๊ท€๋กœ ํŠธ๋ฆฌ ์ˆœํšŒ/ํƒ์ƒ‰์ด ๋งค์šฐ ์ž์—ฐ์Šค๋Ÿฝ๊ณ  ์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐ
  • ๋ฌด๋ฐฉํ–ฅ ํŠธ๋ฆฌ๋Š” visited๋‚˜ parent๋กœ ์—ญ๋ฐฉํ–ฅ ๋ฐฉ์ง€
  • ์™„์ „ ์ด์ง„ ํŠธ๋ฆฌ/ํž™์€ ๋ฐฐ์—ด๋กœ๋„ ๊ตฌํ˜„ ๊ฐ€๋Šฅ

ํŠธ๋ฆฌ ๋ฌธ์ œ๋ฅผ ๋งŒ๋‚  ๋•Œ๋Š” "๋ถ€๋ชจ๊ฐ€ ํ•˜๋Š” ์ผ์„ ์ž์‹๋„ ๋ฐ˜๋ณต"ํ•˜๋Š” ๊ตฌ์กฐ๋ฅผ ๋– ์˜ฌ๋ฆฌ๋ฉด, ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์žฌ๊ท€๋กœ ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


ํŠธ๋ฆฌ ์ˆœํšŒ(Tree Traversal)

ํŠธ๋ฆฌ ์ˆœํšŒ๋Š” ํŠธ๋ฆฌ์˜ ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ์ฒด๊ณ„์ ์œผ๋กœ ๋ฐฉ๋ฌธํ•˜๋Š” ๊ธฐ์ˆ ์ž…๋‹ˆ๋‹ค.
์ฃผ์š” ๋ฐฉ๋ฒ•์œผ๋กœ DFS ๊ธฐ๋ฐ˜ ์ „์œ„/์ค‘์œ„/ํ›„์œ„ ์ˆœํšŒ์™€ BFS ๊ธฐ๋ฐ˜ ๋ ˆ๋ฒจ ์ˆœํšŒ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ฐ ์ˆœํšŒ ๋ฐฉ์‹์˜ ํŠน์ง•๊ณผ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์„ ์˜ˆ์ œ ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


ํŠธ๋ฆฌ ์ˆœํšŒ์˜ ๊ธฐ๋ณธ ๊ฐœ๋…

๋ฐฉ๋ฌธ(Visit) vs ์ˆœํšŒ(Traversal)

  • ๋ฐฉ๋ฌธ: ๋…ธ๋“œ์˜ ๊ฐ’์„ ์ถœ๋ ฅ/๊ณ„์‚ฐ/์ €์žฅํ•˜๋Š” ๊ตฌ์ฒด์ ์ธ ํ–‰์œ„
  • ์ˆœํšŒ: ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ์ฒด๊ณ„์ ์œผ๋กœ ๋ฐฉ๋ฌธํ•˜๊ธฐ ์œ„ํ•œ ์ „์ฒด์ ์ธ ๋™์„ 

ํŠธ๋ฆฌ ๊ตฌ์กฐ ์˜ˆ์‹œ

       A
      / \
     B   C
    / \   \
   D   E   F

๊นŠ์ด ์šฐ์„  ์ˆœํšŒ(DFS)

1. ์ „์œ„ ์ˆœํšŒ (Pre-order)

์ˆœ์„œ: ๋ถ€๋ชจ โ†’ ์™ผ์ชฝ ์ž์‹ โ†’ ์˜ค๋ฅธ์ชฝ ์ž์‹
ํ™œ์šฉ: ํŠธ๋ฆฌ ๊ตฌ์กฐ ๋ณต์ œ, ํ‘œํ˜„์‹ ์ „์œ„ ํ‘œ๊ธฐ๋ฒ•

void preOrder(Node root) {
    if (root == null) return;
    System.out.print(root.value); // ํ˜„์žฌ ๋…ธ๋“œ ๋ฐฉ๋ฌธ
    preOrder(root.left);          // ์™ผ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ
    preOrder(root.right);         // ์˜ค๋ฅธ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ
}

์‹คํ–‰ ๊ฒฐ๊ณผ: ABDECF

2. ์ค‘์œ„ ์ˆœํšŒ (In-order)

์ˆœ์„œ: ์™ผ์ชฝ ์ž์‹ โ†’ ๋ถ€๋ชจ โ†’ ์˜ค๋ฅธ์ชฝ ์ž์‹
ํ™œ์šฉ: ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ(BST) ๊ฐ’ ์ •๋ ฌ

void inOrder(Node root) {
    if (root == null) return;
    inOrder(root.left);           // ์™ผ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ
    System.out.print(root.value); // ํ˜„์žฌ ๋…ธ๋“œ ๋ฐฉ๋ฌธ
    inOrder(root.right);          // ์˜ค๋ฅธ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ
}

์‹คํ–‰ ๊ฒฐ๊ณผ: DBEACF

3. ํ›„์œ„ ์ˆœํšŒ (Post-order)

์ˆœ์„œ: ์™ผ์ชฝ ์ž์‹ โ†’ ์˜ค๋ฅธ์ชฝ ์ž์‹ โ†’ ๋ถ€๋ชจ
ํ™œ์šฉ: ํŠธ๋ฆฌ ์‚ญ์ œ, ํ‘œํ˜„์‹ ํ›„์œ„ ํ‘œ๊ธฐ๋ฒ•

void postOrder(Node root) {
    if (root == null) return;
    postOrder(root.left);         // ์™ผ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ
    postOrder(root.right);        // ์˜ค๋ฅธ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ
    System.out.print(root.value); // ํ˜„์žฌ ๋…ธ๋“œ ๋ฐฉ๋ฌธ
}

์‹คํ–‰ ๊ฒฐ๊ณผ: DEBFCA


๋„ˆ๋น„ ์šฐ์„  ์ˆœํšŒ(BFS)

4. ๋ ˆ๋ฒจ ์ˆœํšŒ (Level-order)

์ˆœ์„œ: ๋ ˆ๋ฒจ 0 โ†’ ๋ ˆ๋ฒจ 1 โ†’ ๋ ˆ๋ฒจ 2
ํ™œ์šฉ: ์ตœ๋‹จ ๊ฒฝ๋กœ ํƒ์ƒ‰, ๊ณ„์ธต๋ณ„ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ

void levelOrder(Node root) {
    Queue q = new LinkedList<>();
    q.add(root);
    
    while (!q.isEmpty()) {
        Node cur = q.poll();
        System.out.print(cur.value);
        
        if (cur.left != null) q.add(cur.left);
        if (cur.right != null) q.add(cur.right);
    }
}

์‹คํ–‰ ๊ฒฐ๊ณผ: ABCDEF


์‹œ๊ฐ„ ๋ณต์žก๋„ ๋น„๊ต

์ˆœํšŒ ๋ฐฉ์‹์‹œ๊ฐ„ ๋ณต์žก๋„๊ณต๊ฐ„ ๋ณต์žก๋„
์ „์œ„/์ค‘์œ„/ํ›„์œ„O(N)O(H)
๋ ˆ๋ฒจ ์ˆœํšŒO(N)O(W)
  • N: ์ „์ฒด ๋…ธ๋“œ ์ˆ˜
  • H: ํŠธ๋ฆฌ ๋†’์ด
  • W: ํŠธ๋ฆฌ ์ตœ๋Œ€ ๋„ˆ๋น„

ํ™œ์šฉ ํŒ

  1. ํŠธ๋ฆฌ ๋ณต์ œ โ†’ ์ „์œ„ ์ˆœํšŒ
  2. ๊ฐ’ ์ •๋ ฌ ํ•„์š” โ†’ ์ค‘์œ„ ์ˆœํšŒ
  3. ํ›„์ฒ˜๋ฆฌ ํ•„์š” โ†’ ํ›„์œ„ ์ˆœํšŒ
  4. ๋ ˆ๋ฒจ๋ณ„ ์ฒ˜๋ฆฌ โ†’ ๋ ˆ๋ฒจ ์ˆœํšŒ
  5. ๋ฉ”๋ชจ๋ฆฌ ์ œ์•ฝ โ†’ ๋ฐ˜๋ณต๋ฌธ ๊ตฌํ˜„ ๊ถŒ์žฅ

profile
๊ณ ๊ฐ์—๊ฒŒ ์‹ ๋ขฐ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์ž ์•ˆํƒœํ˜„์ž…๋‹ˆ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€