Post

🐹 4. Trees and Graphs

[ 트리의 μ’…λ₯˜ ]

νŠΈλ¦¬λŠ” λ…Έλ“œλ‘œ 이루어진 μžλ£Œκ΅¬μ‘°μ΄λ‹€.

  • νŠΈλ¦¬λŠ” ν•˜λ‚˜μ˜ 루트 λ…Έλ“œλ₯Ό κ°–λŠ”λ‹€
  • 루트 λ…Έλ“œλŠ” 0개 μ΄μƒμ˜ μžμ‹ λ…Έλ“œλ₯Ό κ°–κ³  μžˆλ‹€.
  • κ·Έ μžμ‹ λ…Έλ“œ λ˜ν•œ 0개 μ΄μƒμ˜ μžμ‹ λ…Έλ“œλ₯Ό κ°–κ³  있고, μ΄λŠ” 반볡적으둜 μ •μ˜λœλ‹€.

νŠΈλ¦¬μ—λŠ” 사이클(cycle)이 μ‘΄μž¬ν•  수 μ—†λ‹€. λ…Έλ“œλ“€μ€ νŠΉμ • μˆœμ„œλ‘œ λ‚˜μ—΄λ  μˆ˜λ„ 있고 그럴 수 없을 μˆ˜λ„ μžˆλ‹€. 각 λ…Έλ“œλŠ” μ–΄λ–€ μžλ£Œν˜•μœΌλ‘œλ„ ν‘œν˜„ κ°€λŠ₯ν•˜λ‹€.

Node 클래슀λ₯Ό κ°„λ‹¨ν•˜κ²Œ μ •μ˜ν•˜λ©΄ λ‹€μŒκ³Ό κ°™λ‹€.

1
2
3
4
class Node {
    public String name;
    public Node[] children;
}

λ…Έλ“œ 클래슀λ₯Ό ν¬ν•¨ν•˜λŠ” Tree 클래슀λ₯Ό μ •μ˜ν•  μˆ˜λ„ μžˆμ§€λ§Œ, ꡳ이 ν•˜μ§€ μ•Šκ² λ‹€.

트리 vs μ΄μ§„νŠΈλ¦¬

μ΄μ§„νŠΈλ¦¬(binary tree) : 각 λ…Έλ“œκ°€ μ΅œλŒ€ 두 개의 μžμ‹μ„ κ°–λŠ” 트리

λͺ¨λ“  νŠΈλ¦¬κ°€ μ΄μ§„νŠΈλ¦¬λŠ” μ•„λ‹ˆλ‹€.

μžμ‹μ΄ μ—†λŠ” λ…Έλ“œλŠ” β€˜λ§λ‹¨β€™ λ…Έλ“œλΌκ³  λΆ€λ₯Έλ‹€.

이진 트리 vs 이진 탐색 트리

이진 탐색 트리 : λͺ¨λ“  λ…Έλ“œκ°€ β€˜λͺ¨λ“  μ™Όμͺ½ μžμ‹λ“€ ≀ n < λͺ¨λ“  였λ₯Έμͺ½ μžμ‹λ“€β€™ 속성을 κ°€μ§€λŠ” μ΄μ§„νŠΈλ¦¬

트리 λ¬Έμ œκ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ 보톡 이진 탐색 트리일 것이라 κ°€μ •ν•΄ λ²„λ¦¬λŠ”λ°, 이진 탐색 νŠΈλ¦¬μΈμ§€ μ•„λ‹Œμ§€ ν™•μ‹€νžˆ ν•˜λ„λ‘ ν•΄μ•Όν•œλ‹€.

κ· ν˜• vs λΉ„κ· ν˜•

κ· ν˜•μ„ μž‘λŠ”λ‹€λŠ” 것이 μ™Όμͺ½κ³Ό 였λ₯Έμͺ½ λΆ€λΆ„ 트리의 크기가 μ™„μ „νžˆ κ°™κ²Œ ν•˜λŠ” 것을 μ˜λ―Έν•˜μ§€ μ•ŠλŠ”λ‹€. β€˜κ· ν˜•β€™ νŠΈλ¦¬μΈμ§€ μ•„λ‹Œμ§€ ν™•μΈν•˜λŠ” 방법 쀑 ν•˜λ‚˜λŠ” β€˜λ„ˆλ¬΄ λΆˆκ· ν˜•ν•œκ±΄ μ•„λ‹Œμ§€β€™ ν™•μΈν•˜λŠ” 것 μ΄μƒμ˜ 의미λ₯Ό κ°–λŠ”λ‹€. O(logN) μ‹œκ°„μ— insert와 findλ₯Ό ν•  수 μžˆμ„ μ •λ„λ‘œ κ· ν˜•μ΄ 잘 μž‘ν˜€ μžˆμ§€λ§Œ, κ·Έλ ‡λ‹€κ³  κΌ­ μ™„λ²½ν•˜κ²Œ κ· ν˜• μž‘ν˜€ μžˆμ„ ν•„μš”λŠ” μ—†λ‹€.

  • κ· ν˜• 트리의 일반적 μœ ν˜•
    • λ ˆλ“œ-λΈ”λž™ 트리
    • AVL 트리

μ™„μ „ 이진 트리(complete binary tree)

: 트리의 λͺ¨λ“  λ†’μ΄μ—μ„œ λ…Έλ“œκ°€ 꽉 μ°¨ μžˆλŠ” 이진 트리

λ§ˆμ§€λ§‰ 단계(level)λŠ” 꽉 μ°¨ μžˆμ§€ μ•Šμ•„λ„ λ˜μ§€λ§Œ λ…Έλ“œκ°€ μ™Όμͺ½μ—μ„œ 였λ₯Έμͺ½μœΌλ‘œ μ±„μ›Œμ Έμ•Ό ν•œλ‹€.

μ „ 이진 트리(full binary tree)

: λͺ¨λ“  λ…Έλ“œμ˜ μžμ‹μ΄ μ—†κ±°λ‚˜ μ •ν™•νžˆ 두 개 μžˆλŠ” 경우

μžμ‹μ΄ ν•˜λ‚˜λ§Œ μžˆλŠ” λ…Έλ“œκ°€ μ‘΄μž¬ν•΄μ„œλŠ” μ•ˆ λœλ‹€.

포화 이진 트리(perfect binary tree)

: μ „ 이진 νŠΈλ¦¬μ΄λ©΄μ„œ μ™„μ „ 이진 트리인 경우

λͺ¨λ“  말단 λ…Έλ“œλŠ” 같은 높이에 μžˆμ–΄μ•Ό ν•˜λ©°, λ§ˆμ§€λ§‰ λ‹¨κ³„μ—μ„œ λ…Έλ“œμ˜ κ°œμˆ˜κ°€ μ΅œλŒ€κ°€ λ˜μ–΄μ•Ό ν•œλ‹€.

포화 이진 νŠΈλ¦¬λŠ” λ…Έλ“œμ˜ κ°œμˆ˜κ°€ μ •ν™•νžˆ \(2^{k-1}\) (\(k\)λŠ” 트리의 높이)κ°œμ—¬μ•Ό ν•œλ‹€.

[ 이진 트리 순회 ]

μ€‘μœ„(in-order), ν›„μœ„(post-order), μ „μœ„(pre-order)

이 쀑 κ°€μž₯ λΉˆλ²ˆν•˜κ²Œ μ‚¬μš©λ˜λŠ” 순회 방식은 μ€‘μœ„ μˆœνšŒμ΄λ‹€.

μ€‘μœ„ 순회(in-order traversal)

: μ™Όμͺ½ 가지(branch), ν˜„μž¬ λ…Έλ“œ, 였λ₯Έμͺ½ 가지 μˆœμ„œλ‘œ λ…Έλ“œλ₯Ό β€˜λ°©λ¬Έβ€™ν•˜κ³  좜λ ₯ν•˜λŠ” 방법

1
2
3
4
5
6
7
void inOrderTraversal(TreeNode node) {
    if (node != null) {
        inOrderTraversal(node.left);
        visit(node);
        inOrderTraversal(node.right);
    }
}

이진 탐색 트리λ₯Ό 이 λ°©μ‹μœΌλ‘œ μˆœνšŒν•œλ‹€λ©΄ μ˜€λ¦„μ°¨μˆœμœΌλ‘œ λ°©λ¬Έν•˜κ²Œ λœλ‹€.

μ „μœ„ 순회(pre-order traversal)

: μžμ‹ λ…Έλ“œλ³΄λ‹€ ν˜„μž¬ λ…Έλ“œλ₯Ό λ¨Όμ € λ°©λ¬Έν•˜λŠ” 방법

1
2
3
4
5
6
7
void preOrderTraversal(TreeNode node) {
    if (node != null) {
        visit(node);
        preOrderTraversal(node.left);
        preOrderTraversal(node.right);
    }
}

μ „μœ„ μˆœνšŒμ—μ„œ κ°€μž₯ λ¨Όμ € λ°©λ¬Έν•˜κ²Œ 될 λ…Έλ“œλŠ” μ–Έμ œλ‚˜ λ£¨νŠΈμ΄λ‹€.

ν›„μœ„ 순회(post-order traversal)

: λͺ¨λ“  μžμ‹ λ…Έλ“œλ“€μ„ λ¨Όμ € λ°©λ¬Έν•œ λ’€ λ§ˆμ§€λ§‰μ— ν˜„μž¬ λ…Έλ“œλ₯Ό λ°©λ¬Έν•˜λŠ” 방법

1
2
3
4
5
6
7
void postOrderTraversal(TreeNode node) {
    if (node != null) {
        postOrderTraversal(node.left);
        postOrderTraversal(node.right);
        visit(node);
    }
}

ν›„μœ„ μˆœνšŒμ—μ„œ κ°€μž₯ λ§ˆμ§€λ§‰μ— λ°©λ¬Έν•˜κ²Œ 될 λ…Έλ“œλŠ” μ–Έμ œλ‚˜ λ£¨νŠΈμ΄λ‹€.

[ 이진 νž™(μ΅œμ†Œνž™κ³Ό μ΅œλŒ€νž™) ]

μ΅œμ†Œνž™(min-heaps)만 λ‹€λ£° 것이닀. μ΅œλŒ€νž™(max-heaps)은 μ›μ†Œκ°€ λ‚΄λ¦Όμ°¨μˆœμœΌλ‘œ μ •λ ¬λ˜μ–΄ μžˆλ‹€λŠ” 점만 λ‹€λ₯Ό 뿐, μ΅œμ†Œνž™κ³Ό μ™„μ „νžˆ κ°™λ‹€.

μ΅œμ†Œνž™μ€ 트리의 λ§ˆμ§€λ§‰ λ‹¨κ³„μ—μ„œ 였λ₯Έμͺ½ 뢀뢄을 λΊ€ λ‚˜λ¨Έμ§€ 뢀뢄이 가득 μ±„μ›Œμ Έ μžˆλ‹€λŠ” μ μ—μ„œ μ™„μ „ 이진 트리이며, 각 λ…Έλ“œμ˜ μ›μ†Œκ°€ μžμ‹λ“€μ˜ μ›μ†Œλ³΄λ‹€ μž‘λ‹€λŠ” νŠΉμ„±μ΄ μžˆλ‹€. λ”°λΌμ„œ λ£¨νŠΈλŠ” 트리 μ „μ²΄μ—μ„œ κ°€μž₯ μž‘μ€ μ›μ†Œκ°€ λœλ‹€.

μ΅œμ†Œνž™μ—λŠ” insert와 extract_minμ΄λΌλŠ” 핡심 μ—°μ‚° 두 가지가 μ‘΄μž¬ν•œλ‹€.

μ‚½μž…

μ΅œμ†Œνž™μ— μ›μ†Œλ₯Ό μ‚½μž…ν•  λ•ŒλŠ” μ–Έμ œλ‚˜ 트리의 λ°‘λ°”λ‹₯μ—μ„œλΆ€ν„° μ‚½μž…μ„ μ‹œμž‘ν•œλ‹€. μ™„μ „ 트리의 속성에 μœ„λ°°λ˜μ§€ μ•Šκ²Œ μƒˆλ‘œμš΄ μ›μ†ŒλŠ” λ°‘λ°”λ‹₯ κ°€μž₯ 였λ₯Έμͺ½ μœ„μΉ˜λ‘œ μ‚½μž…λœλ‹€.

μƒˆλ‘œ μ‚½μž…λœ μ›μ†Œκ°€ μ œλŒ€λ‘œ 된 자리λ₯Ό 찾을 λ•ŒκΉŒμ§€ λΆ€λͺ¨ λ…Έλ“œμ™€ κ΅ν™˜ν•΄λ‚˜κ°„λ‹€. 기본적으둜 이와 같은 λ°©μ‹μœΌλ‘œ μ΅œμ†Œ μ›μ†Œλ₯Ό μœ„μͺ½μœΌλ‘œ μ˜¬λ¦°λ‹€.

νž™μ— μžˆλŠ” λ…Έλ“œμ˜ 개수λ₯Ό n이라 ν•  λ•Œ μœ„μ˜ 연산은 O(log n) μ‹œκ°„μ΄ κ±Έλ¦°λ‹€.

μ΅œμ†Œ μ›μ†Œ 뽑아내기

μ΅œμ†Œνž™μ—μ„œ μ΅œμ†Œ μ›μ†ŒλŠ” μ–Έμ œκ°€ κ°€μž₯ μœ„μ— 놓인닀.

  1. μ΅œμ†Œ μ›μ†Œλ₯Ό μ œκ±°ν•œ 후에 νž™μ— μžˆλŠ” κ°€μž₯ λ§ˆμ§€λ§‰ μ›μ†Œ(λ°‘λ°”λ‹₯ κ°€μž₯ μ™Όμͺ½)와 κ΅ν™˜ν•œλ‹€.
  2. μ΅œμ†Œνž™μ˜ μ„±μ§ˆμ„ λ§Œμ‘±ν•˜λ„λ‘, ν•΄λ‹Ή λ…Έλ“œλ₯Ό μžμ‹ λ…Έλ“œμ™€ κ΅ν™˜ν•΄ λ‚˜κ°μœΌλ‘œμ¨ λ°‘μœΌλ‘œ 내보낸닀.(μ™Όμͺ½ μ›μ†Œ, 였λ₯Έμͺ½ μ›μ†Œ 쀑 더 μž‘μ€ μ›μ†Œμ™€ κ΅ν™˜)

O(log n) μ‹œκ°„μ΄ κ±Έλ¦°λ‹€.

[ 트라이(접두사 트리) ]

: nμ°¨ 트리(n-ary tree)의 λ³€μ’…μœΌλ‘œ 각 λ…Έλ“œμ— 문자λ₯Ό μ €μž₯ν•˜λŠ” 자료ꡬ쑰

트리λ₯Ό μ•„λž˜μͺ½μœΌλ‘œ μˆœνšŒν•˜λ©΄ 단어 ν•˜λ‚˜κ°€ λ‚˜μ˜¨λ‹€.

널 λ…Έλ“œ(null node)라고도 λΆˆλ¦¬μš°λŠ” β€˜* λ…Έλ“œβ€™λŠ” μ’…μ’… λ‹¨μ–΄μ˜ 끝을 λ‚˜νƒ€λ‚Έλ‹€.

ex) MANY 이후 β€˜* λ…Έλ“œβ€™κ°€ λ‚˜μ˜€λ©΄ MANYλΌλŠ” 단어가 μ™„μ„±λ˜μ—ˆμŒμ„ μ•Œλ¦°λ‹€.

MAλΌλŠ” κ²½λ‘œκ°€ μ‘΄μž¬ν•œλ‹€λŠ” 사싀은 MA둜 μ‹œμž‘ν•˜λŠ” 단어가 μžˆλ‹€λŠ” 것이닀.

νŠΈλΌμ΄μ—μ„œ 각 λ…Έλ“œλŠ” 1κ°œμ—μ„œ ALPHABET_SIZE + 1κ°œκΉŒμ§€ μžμ‹μ„ κ°–κ³  μžˆμ„ 수 μžˆλ‹€. (λ§Œμ•½ β€˜* λ…Έλ“œβ€™ λŒ€μ‹  boolean ν”Œλž˜κ·Έλ‘œ ν‘œν˜„ν–ˆλ‹€λ©΄ 0κ°œμ—μ„œ ALPHABET_SIZEκΉŒμ§€)

접두사λ₯Ό λΉ λ₯΄κ²Œ 찾아보기 μœ„ν•œ μ•„μ£Ό ν”ν•œ λ°©μ‹μœΌλ‘œ, λͺ¨λ“  μ–Έμ–΄λ₯Ό νŠΈλΌμ΄μ— μ €μž₯ν•΄λ†“λŠ” 방식이 μžˆλ‹€.

ν•΄μ‹œν…Œμ΄λΈ”μ„ μ΄μš©ν•˜λ©΄ 주어진 λ¬Έμžμ—΄μ΄ μœ νš¨ν•œμ§€ μ•„λ‹Œμ§€ λΉ λ₯΄κ²Œ 확인할 수 μžˆμ§€λ§Œ, κ·Έ λ¬Έμžμ—΄μ΄ μ–΄λ–€ μœ νš¨ν•œ λ‹¨μ–΄μ˜ 접두사인지 확인할 μˆ˜λŠ” μ—†λ‹€. 트라이λ₯Ό μ΄μš©ν•˜λ©΄ μ•„μ£Ό λΉ λ₯΄κ²Œ 확인할 수 μžˆλ‹€.

β†’ νŠΈλΌμ΄λŠ” 길이가 K인 λ¬Έμžμ—΄μ΄ μ£Όμ–΄μ‘Œμ„ λ•Œ O(K) μ‹œκ°„μ— ν•΄λ‹Ή λ¬Έμžμ—΄μ΄ μœ νš¨ν•œ 접두사인지 확인할 수 μžˆλ‹€. 이 μ‹œκ°„μ€ ν•΄μ‹œν…Œμ΄λΈ”μ„ μ‚¬μš©ν–ˆμ„ λ•Œμ™€ μ •ν™•νžˆ 같은 μˆ˜ν–‰ μ‹œκ°„μ΄λ‹€. 검색 O(1) μž…λ ₯ λ¬Έμžμ—΄ 읽기 O(K)

μœ νš¨ν•œ 단어 집합을 μ΄μš©ν•˜λŠ” λ§Žμ€ λ¬Έμ œλ“€μ€ 트라이λ₯Ό 톡해 μ΅œμ ν™”ν•  수 μžˆλ‹€.

νŠΈλ¦¬μ—μ„œ μ—°κ΄€λœ 접두사λ₯Ό 반볡적으둜 검색해야 ν•˜λŠ” μƒν™©μ—μ„œ(ex. M, MA, MAN, MANYλ₯Ό μ°¨λ‘€λŒ€λ‘œ μ‚΄νŽ΄λ³΄λŠ” 상황), 트리의 ν˜„μž¬ λ…Έλ“œλ₯Ό μ°Έμ‘°κ°’μœΌλ‘œ λ„˜κΈΈ μˆ˜λ„ μžˆλ‹€. β†’ 검색할 λ•Œλ§ˆλ‹€ λ£¨νŠΈμ—μ„œ μ‹œμž‘ν•  ν•„μš”κ°€ μ—†κ³ , λ‹¨μˆœνžˆ Yκ°€ MAN의 μžμ‹μΈμ§€λ§Œ 확인해보면 λœλ‹€.

[ κ·Έλž˜ν”„ ]

트리(tree)λŠ” κ·Έλž˜ν”„(graph)의 ν•œ μ’…λ₯˜μ΄λ‹€. νŠΈλ¦¬λŠ” 사이크이 μ—†λŠ” ν•˜λ‚˜μ˜ μ—°κ²° κ·Έλž˜ν”„μ΄λ‹€.

κ·Έλž˜ν”„: λ‹¨μˆœνžˆ λ…Έλ“œμ™€ κ·Έ λ…Έλ“œλ₯Ό μ—°κ²°ν•˜λŠ” κ°„μ„ (edge)을 ν•˜λ‚˜λ‘œ λͺ¨μ•„ 놓은 것

  • κ·Έλž˜ν”„μ—λŠ” λ°©ν–₯성이 μžˆμ„ μˆ˜λ„ 있고 없을 μˆ˜λ„ μžˆλ‹€.
    • λ°©ν–₯μ„±O : 일방톡행
    • λ°©ν–₯μ„±X : μ–‘λ°©ν–₯ 톡행
  • κ·Έλž˜ν”„λŠ” μ—¬λŸ¬ 개의 고립된 λΆ€λΆ„ κ·Έλž˜ν”„λ‘œ ꡬ성될 수 μžˆλ‹€.
  • κ·Έλž˜ν”„μ—λŠ” 사이클이 μ‘΄μž¬ν•  μˆ˜λ„ 있고 μ‘΄μž¬ν•˜μ§€ μ•Šμ„ μˆ˜λ„ μžˆλ‹€.
    • 사이클 μ—†λŠ” κ·Έλž˜ν”„λŠ” β€˜λΉ„μˆœν™˜ κ·Έλž˜ν”„β€™(acycle graph)라고 λΆ€λ₯Έλ‹€.

인접 리슀트(adjacency list)

κ·Έλž˜ν”„λ₯Ό ν‘œν˜„ν•  λ•Œ μ‚¬μš©λ˜λŠ” κ°€μž₯ 일반적인 λ°©λ²•μœΌλ‘œ λͺ¨λ“  정점(ν˜Ήμ€ λ…Έλ“œ)λ₯Ό 인접 λ¦¬μŠ€νŠΈμ— μ €μž₯ν•œλ‹€. 무방ν–₯ κ·Έλž˜ν”„μ—μ„œ (a, b) 간선은 두 번 μ €μž₯λœλ‹€.

κ·Έλž˜ν”„μ—μ„œ λ…Έλ“œλ₯Ό μ •μ˜ν•˜λŠ” κ°„λ‹¨ν•œ ν΄λž˜μŠ€λŠ” 트리의 λ…Έλ“œ ν΄λž˜μŠ€μ™€ ꢁ극적으둜 κ°™μ•„ 보인닀.

1
2
3
4
5
6
7
class Graph {
    public Node[] nodes;
}
class Node {
    public String name;
    public Node[] children;
}

νŠΈλ¦¬μ—μ„  νŠΉμ • λ…Έλ“œ ν•˜λ‚˜μ—μ„œ λ‹€λ₯Έ λ…Έλ“œλ‘œ λͺ¨λ‘ μ ‘κ·Ό κ°€λŠ₯ν•˜κΈ° λ•Œλ¬Έμ— Tree 클래슀λ₯Ό λ”°λ‘œ 두지 μ•Šμ•˜λ‹€. ν•˜μ§€λ§Œ κ·Έλž˜ν”„λŠ” νŠΈλ¦¬μ™€ 달리 νŠΉμ • λ…Έλ“œμ—μ„œ λ‹€λ₯Έ λͺ¨λ“  λ…Έλ“œλ‘œ 접근이 κ°€λŠ₯ν•˜μ§€λŠ” μ•Šμ•„ Graph λΌλŠ” 클래슀λ₯Ό μ‚¬μš©ν•œλ‹€.

인접 ν–‰λ ¬

$N\times N$ 뢈린 ν–‰λ ¬(boolean matrix)둜써 matrix[i][j]κ°€ true라면 iμ—μ„œ j둜의 간선이 μžˆλ‹€λŠ” λœ»μ΄λ‹€. μ—¬κΈ°μ„œ N은 λ…Έλ“œμ˜ 개수λ₯Ό λœ»ν•œλ‹€.

κ·Έλž˜ν”„ 탐색

일반적인 λ°©λ²•μœΌλ‘œλŠ” 깊이 μš°μ„  탐색(depth-first search), λ„ˆλΉ„ μš°μ„  탐색(breadth-first search)이 μžˆλ‹€.

  • 깊이 μš°μ„  탐색(DFS)
    • 루트 λ…Έλ“œμ—μ„œ μ‹œμž‘ν•˜μ—¬ ν•΄λ‹Ή λΆ„κΈ°λ₯Ό μ™„λ²½ν•˜κ²Œ νƒμƒ‰ν•˜λŠ” 방법
    • κ·Έλž˜ν”„μ—μ„œ λͺ¨λ“  λ…Έλ“œλ₯Ό λ°©λ¬Έν•˜κ³ μž ν•  λ•Œ 더 μ„ ν˜Έλ¨
  • λ„ˆλΉ„ μš°μ„  탐색(BFS)
    • 루트 λ…Έλ“œμ—μ„œ μ‹œμž‘ν•΄μ„œ μΈμ ‘ν•œ λ…Έλ“œλ₯Ό λ¨Όμ € νƒμƒ‰ν•˜λŠ” 방법
    • μ΅œλ‹¨ 경둜 ν˜Ήμ€ μž„μ˜μ˜ 경둜λ₯Ό μ°Ύκ³  싢을 λ•Œ μ„ ν˜Έλ¨

깊이 μš°μ„  탐색(DFS)

a λ…Έλ“œλ₯Ό λ°©λ¬Έν•œ λ’€ a와 μΈμ ‘ν•œ λ…Έλ“œλ“€μ„ μ°¨λ‘€λ‘œ μˆœνšŒν•œλ‹€.

μ „μœ„ 순회λ₯Ό ν¬ν•¨ν•œ λ‹€λ₯Έ ν˜•νƒœμ˜ 트리 μˆœνšŒλŠ” λͺ¨λ‘ DFS의 ν•œ μ’…λ₯˜μ΄λ‹€.

이 μ•Œκ³ λ¦¬μ¦˜μ„ κ΅¬ν˜„ν•  λ•Œ κ°€μž₯ 큰 차이점은, κ·Έλž˜ν”„ νƒμƒ‰μ˜ 경우 μ–΄λ–€ λ…Έλ“œλ₯Ό λ°©λ¬Έν–ˆμ—ˆλŠ”μ§€ μ—¬λΆ€λ₯Ό λ°˜λ“œμ‹œ 검사해야 ν•œλ‹€λŠ” 것이닀. 이λ₯Ό κ²€μ‚¬ν•˜μ§€ μ•Šμ„ 경우 λ¬΄ν•œλ£¨ν”„μ— 빠질 μœ„ν—˜μ΄ μžˆλ‹€.

1
2
3
4
5
6
7
8
9
10
void search(Node root) {
    if (root == null) return;
    visit(root);
    root.visited = true;
    for each (Node n in root.adjacent) {
        if (n.visited == false) {
                search(n);
        }
    }
}

λ„ˆλΉ„ μš°μ„  탐색(BFS)

BFSλŠ” μž¬κ·€μ μœΌλ‘œ λ™μž‘ν•˜μ§€ μ•ŠλŠ”λ‹€. 큐(queue)λ₯Ό μ‚¬μš©ν•œλ‹€.

a λ…Έλ“œμ—μ„œ μ‹œμž‘ν•œλ‹€κ³  ν–ˆμ„ λ•Œ, BFSλŠ” a λ…Έλ“œμ˜ 이웃 λ…Έλ“œλ₯Ό λͺ¨λ‘ λ°©λ¬Έν•œ λ‹€μŒμ— μ΄μ›ƒμ˜ 이웃듀을 λ°©λ¬Έν•œλ‹€. 즉, 거리에 따라 λ‹¨κ³„λ³„λ‘œ νƒμƒ‰ν•œλ‹€.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void search(Node root) {
    Queue queue = new Queue();
    root.marked = true;
    queue.enqueue(root); // 큐의 끝에 μΆ”κ°€ν•œλ‹€.

    while (!queue.isEmpty()) {
        Node r = queue.dequeue(); // 큐의 μ•žμ—μ„œ 뽑아낸닀.
        visit(r);
        foreach (Node n in r.adjacent) {
            if (n.marked == false) {
                n.marked = true;
                queue.enqueue(n);
            }
        }
    }
}

μ–‘λ°©ν–₯ 탐색

μ–‘λ°©ν–₯ 탐색(bidirectional search)은 μΆœλ°œμ§€μ™€ 도착지 사이에 μ΅œλ‹¨ 경둜λ₯Ό 찾을 λ•Œ μ‚¬μš©λ˜κ³€ ν•œλ‹€. 기본적으둜 μΆœλ°œμ§€μ™€ 도착지 두 λ…Έλ“œμ—μ„œ λ™μ‹œμ— λ„ˆλΉ„ μš°μ„  탐색을 μˆ˜ν–‰ν•œ λ’€, 두 탐색 지점이 μΆ©λŒν•˜λŠ” κ²½μš°μ— 경둜λ₯Ό μ°ΎλŠ” 방식이닀.

μ–‘λ°©ν–₯ 탐색 방식이 μ™œ 더 λΉ λ₯Έμ§€ μ‚΄νŽ΄λ³Έλ‹€. λͺ¨λ“  λ…Έλ“œκ°€ 적어도 k개의 이웃 λ…Έλ“œμ™€ μ—°κ²°λ˜μ–΄ 있고 sμ—μ„œ t둜의 μ΅œλ‹¨ 거리가 dκ°€ λ˜λŠ” κ·Έλž˜ν”„λ₯Ό 생각해 보자.

  • 전톡적인 BFSλ₯Ό μ‚¬μš©ν•œλ‹€λ©΄ 첫 λ‹¨κ³„μ—μ„œ k개의 λ…Έλ“œλ₯Ό 탐색해야 ν•œλ‹€. λ‹€μŒ 단계에선 k개의 λ…Έλ“œλ“€ λ˜ν•œ μ΄μ›ƒν•œ k개의 λ…Έλ“œλ₯Ό 탐색해야 ν•˜λ―€λ‘œ 총 $k^2$개의 λ…Έλ“œλ₯Ό 탐색해야 ν•œλ‹€.

    β†’ λ”°λΌμ„œ 이λ₯Ό d번 λ°˜λ³΅ν•˜λ©΄ 총 $O(k^d)$개의 λ…Έλ“œλ₯Ό 탐색해야 ν•œλ‹€.

  • μ–‘λ°©ν–₯ 탐색을 μ‚¬μš©ν•œλ‹€λ©΄ 두 탐색 μ•Œκ³ λ¦¬μ¦˜μ΄ λŒ€λž΅ d/2 단계(s와 t μ‚¬μ΄μ˜ 쀑간지점)κΉŒμ§€ νƒμƒ‰ν•œ 후에 μΆ©λŒν•  것이닀. λ”°λΌμ„œ s와 t κ°κ°μ—μ„œ λ°©λ¬Έν•˜κ²Œ 될 λ…Έλ“œμ˜ μˆ˜λŠ” λŒ€λž΅ $k^{d/2}$κ°œκ°€ 될 것이고,

    β†’ λ”°λΌμ„œ λ°©λ¬Έν•˜κ²Œ 될 전체 λ…Έλ“œλŠ” λŒ€λž΅ $2k^{d/2}$, $O(k^{d/2})$κ°œκ°€ λœλ‹€.

This post is licensed under CC BY 4.0 by the author.