관리 메뉴

Daehyunii's Dev-blog

21 κ·Έλž˜ν”„ 순회 λ³Έλ¬Έ

πŸ“š Language & CS knowledge/Algorithm & Data structure

21 κ·Έλž˜ν”„ 순회

Daehyunii 2022. 8. 19. 20:29

21.1 κ·Έλž˜ν”„ 순회

  κ·Έλž˜ν”„ μˆœνšŒλž€ 말 κ·ΈλŒ€λ‘œ λͺ¨λ“  λ…Έλ“œ, 즉 κ·Έλž˜ν”„μ— μžˆλŠ” λͺ¨λ“  정점을 λ‹€ λ°©λ¬Έν•œλ‹€λŠ” 말이닀. 트리의 κ²½μš°μ—λŠ” μ°Ύκ³ μžν•˜λŠ” λ…Έλ“œμ— μ ‘κ·Όν•˜λŠ” 길은 λ£¨νŠΈμ—μ„œ μΆœλ°œν•΄μ„œ λ„μ°©ν•˜λŠ” ν•œ 가지 방법밖에 μ—†λ‹€. ν•˜μ§€λ§Œ νŠΈλ¦¬μ™€ λ‹€λ₯΄κ²Œ κ·Έλž˜ν”„λ₯Ό μˆœνšŒν•˜λŠ” κ²½μš°μ—λŠ” λ£¨νŠΈκ°€ λ”°λ‘œ μ—†κΈ° λ•Œλ¬Έμ— μ½”λ“œλ₯Ό κ΅¬ν˜„ν•  λ•ŒλŠ” μ‹œμž‘μ μ„ μ •ν•΄μ€˜μ•Ό ν•œλ‹€. λ˜ν•œ κ·Έλž˜ν”„μ˜ ν•œ λ…Έλ“œμ—μ„œ λ‹€λ₯Έ λ…Έλ“œλ‘œ κ°€λŠ” 방법은 μœ μΌν•œ ν•˜λ‚˜μ˜ λ°©λ²•λ§Œ μ‘΄μž¬ν•œλ‹€λŠ” 보μž₯이 μ—†λ‹€.

 

22.2 깊이 μš°μ„  κ·Έλž˜ν”„ 순회(DFS)

  μ•žμ„œ 배운 이진 탐색 트리의 DFS와 λ™μΌν•œ κ°œλ…μ΄λ‹€. ν•˜μ§€λ§Œ κ·Έλž˜ν”„μ—μ„œλŠ” λ£¨νŠΈκ°€ μ—†κΈ° λ•Œλ¬Έμ— ν•˜λ‚˜μ˜ 정점을 μ§€μ •ν•˜κ³  μ‹œμž‘ν•΄μ•Ό ν•œλ‹€. 그리고 κ·Έλž˜ν”„μ—μ„œμ˜ 깊이 μš°μ„  κ·Έλž˜ν”„ μˆœνšŒλŠ” ν•œ 인접점을 μ°Ύκ³  μ΄μ–΄μ„œ 인접점을 또 μ°ΎλŠ”λ‹€λŠ” μ˜λ―Έμ΄λ‹€. λ‹€μ‹œ 말해 ν•œ 번 λ°©λ¬Έν–ˆλ˜ 곳을 μ œμ™Έν•œ 간선을 톡해 λ‹€λ₯Έ μ—°κ²°λœ μ •μ μœΌλ‘œ 길이 λ§‰νž λ•ŒκΉŒμ§€ μ΄λ™ν•˜λŠ” 것이닀. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— 깊이 μš°μ„  κ·Έλž˜ν”„ μˆœνšŒλŠ” μž¬κ·€ν˜•μœΌλ‘œ λ§Œλ“€κΈ°λ„ ν•˜κ³ , λ°˜λ³΅ν˜•μœΌλ‘œ λ§Œλ“€κΈ°λ„ ν•œλ‹€. κ·Έλž˜ν”„λŠ” μˆœνšŒμ‹œ λ°©λ¬Έν–ˆλ˜ 곳을 κΈ°μ–΅ν•˜λŠ” 것이 맀우 μ€‘μš”ν•˜λ‹€.

 

β—Žμž¬κ·€μ  μš©λ²• μˆ˜λ„μ½”λ“œ

1) μ‹œμž‘ν•˜λŠ” λ…Έλ“œλ₯Ό μž…λ ₯ν•˜λŠ” ν•¨μˆ˜λ₯Ό λ§Œλ“ λ‹€.(λ£¨νŠΈκ°€ μ—†μœΌλ‹ˆ μ‹œμž‘ν•  λ…Έλ“œλ₯Ό 직접 인수둜 λ°›μŒ)

2) 빈 배열을 λ§Œλ“€μ–΄μ„œ μ΅œμ’… κ²°κ³Όλ₯Ό μ €μž₯ν•  λ³€μˆ˜λ₯Ό λ§Œλ“€κ³  λ§ˆμ§€λ§‰μ— 이λ₯Ό λ°˜ν™˜ν•œλ‹€.(κ²°κ³Ό λ°°μ—΄)

3) μˆœνšŒν•œ 정점듀을 좔적 ν•  수 μžˆλŠ” 객체λ₯Ό λ§Œλ“€μ–΄ μ€€λ‹€.(λ°©λ¬Έ 객체)

4) 정점을 μž…λ ₯ν•˜λŠ” 헬퍼 ν•¨μˆ˜λ₯Ό λ§Œλ“ λ‹€.(이 쀑첩 ν•¨μˆ˜κ°€ μž¬κ·€ ν•¨μˆ˜μž„)

5) 헬퍼 ν•¨μˆ˜λŠ” λ°©λ¬Έν•œ 정점을  λ°©λ¬Έ 객체에 λ„£μ–΄μ•Ό ν•œλ‹€.

6) λ°©λ¬Έν•œ 정점은 λ°©λ¬Έ 객체에 λ°©λ¬Έν–ˆλ‹€λŠ” ν‘œμ‹œλ₯Ό ν•˜κ³  κ²°κ³Ό 배열에 μΆ”κ°€ν•΄ μ€€λ‹€.

7) 그리고 λ‚˜λ©΄ ν•΄λ‹Ή μ •μ μ˜ λͺ¨λ“  인접점에 λŒ€ν•œ 루프λ₯Ό λŒλ¦°λ‹€.

8) λ§Œμ•½ λ°©λ¬Έν•˜μ§€ μ•Šμ€ 정점이라면, ν•΄λ‹Ή 정점에 λŒ€ν•΄ 헬퍼 ν•¨μˆ˜λ₯Ό μž¬κ·€ λ°©μ‹μœΌλ‘œ ν˜ΈμΆœν•œλ‹€.

9) λ‚΄λΆ€ ν•¨μˆ˜λŠ” κ²°κ³Ό λ°°μ—΄κ³Ό λ°©λ¬Έ 객체λ₯Ό μ΅œμ‹ ν™”ν•˜λ©΄μ„œ λ°˜λ³΅ν•˜κ²Œ λœλ‹€.

class Graph{
    constructor(){
        this.adjacencyList = {};
    }
    addVertex(vertex){
        if(!this.adjacencyList[vertex]) this.adjacencyList[vertex] = [];
    }
    addEdge(v1,v2){
        this.adjacencyList[v1].push(v2);
        this.adjacencyList[v2].push(v1);
    }
    removeEdge(vertex1,vertex2){
        this.adjacencyList[vertex1] = this.adjacencyList[vertex1].filter(
            v => v !== vertex2
        );
        this.adjacencyList[vertex2] = this.adjacencyList[vertex2].filter(
            v => v !== vertex1
        );
    }
    removeVertex(vertex){
        while(this.adjacencyList[vertex].length){
            const adjacentVertex = this.adjacencyList[vertex].pop();
            this.removeEdge(vertex, adjacentVertex);
        }
        delete this.adjacencyList[vertex]
    }
    depthFirstRecursive(start){
        const result = []; // μˆœνšŒν•œ 정점듀 λͺ¨μ•„λ†“λŠ”κ²ƒ
        const visited = {}; // λ°©λ¬Έν•œ 정점듀 ν™•μΈν•˜λŠ”κ²ƒ
        const adjacencyList = this.adjacencyList; // 이걸 λ”°λ‘œ λ§Œλ“€μ–΄ μ€˜μ•Ό ν•œλ‹€λŠ”κ²ƒμ„ κΌ­ κΈ°μ–΅ν•˜μ…ˆ!
        //μ•„λ‹˜ μ—λŸ¬λ‚¨

        (function dfs(vertex){
            if(!vertex) return null; // μ‹œμž‘μ μ„ 인수둜 μ „λ‹¬ν•˜μ§€ μ•ŠμœΌλ©΄ null을 λ°˜ν™˜ν•΄λΌ 
            visited[vertex] = true;
            result.push(vertex);
            adjacencyList[vertex].forEach(neighbor => {
                if(!visited[neighbor]){
                    return dfs(neighbor)
                }
            });
        })(start);

        return result;
    }
}
//μ •μ μ—μ„œ μ‹œμž‘ -> μ •μ μ˜ κ°„μ„  λ°°μ—΄ 반볡 -> λ°©λ¬Έν•œμ  μ—†μœΌλ©΄ ν•΄λ‹Ή μ •μ μœΌλ‘œ 이동 -> 반볡 -> 
//이동 -> 반볡 -> κ²°κ΅­ λ‹€ λ°©λ¬Έν•˜κ²Œ 되면 -> κ·Έ μ „ μž¬κ·€λ‘œ -> κ·Έ μ „ μž¬κ·€λ‘œ -> κ·Έ μ „ μž¬κ·€λ‘œ -> λ°°μ—΄ λ°˜ν™˜

β—Žλ°˜λ³΅μ  μš©λ²• μˆ˜λ„μ½”λ“œ

1) μŠ€νƒμœΌλ‘œ ν™œμš©ν•  빈 배열을 λ§Œλ“ λ‹€.

2) μŠ€νƒμ— μ‹œμž‘μ μœΌλ‘œ ν™œμš©ν•  정점을 λ„£λŠ”λ‹€.

3) λ§Œμ•½ μŠ€νƒμ΄ 빈 배열이 μƒνƒœκ°€ μ•„λ‹ˆλΌλ©΄ 루프λ₯Ό λŒλ¦°λ‹€. μŠ€νƒμ— 정점이 μžˆλ‹€λ©΄ ν•΄λ‹Ή 정점을 pop() ν•œ λ‹€μŒ 방문을 ν–ˆμ—ˆλŠ”μ§€ ν™•μΈν•œλ‹€.

4) 아직 λ°©λ¬Έν•˜μ§€ μ•Šμ•˜λ‹€λ©΄ λ°©λ¬Έ 객체에 μΆ”κ°€ν•΄ μ€€λ‹€.

5) 그리고 ν•΄λ‹Ή μ •μ μ˜ 인접점에 λŒ€ν•΄ λ°˜λ³΅λ¬Έμ„ ν˜ΈμΆœν•˜κ³  μŠ€νƒμ— μš”μ†Œλ“€μ„ μΆ”κ°€ν•΄ μ€€λ‹€.

(μž¬κ·€ν˜•κ³Ό 같은 DFS λ°©μ‹μ΄μ§€λ§Œ λ°˜ν™˜ν•˜λŠ” 결과의 μˆœμ„œλŠ” λ‹€λ₯΄λ‹€.)

class Graph{
    constructor(){
        this.adjacencyList = {};
    }
    addVertex(vertex){
        if(!this.adjacencyList[vertex]) this.adjacencyList[vertex] = [];
    }
    addEdge(v1,v2){
        this.adjacencyList[v1].push(v2);
        this.adjacencyList[v2].push(v1);
    }
    removeEdge(vertex1,vertex2){
        this.adjacencyList[vertex1] = this.adjacencyList[vertex1].filter(
            v => v !== vertex2
        );
        this.adjacencyList[vertex2] = this.adjacencyList[vertex2].filter(
            v => v !== vertex1
        );
    }
    removeVertex(vertex){
        while(this.adjacencyList[vertex].length){
            const adjacentVertex = this.adjacencyList[vertex].pop();
            this.removeEdge(vertex, adjacentVertex);
        }
        delete this.adjacencyList[vertex]
    }
 
    depthFirstIterative(start){
        const stack = [start];
        const result = [];
        const visited = {};
        let currentVertex;

        visited[start] = true; // μŠ€νƒμ— λ„£κΈ°
        while(stack.length){
            currentVertex = stack.pop(); // μŠ€νƒμ—μ„œ κΊΌλ‚΄κΈ°
            result.push(currentVertex); // 결과에 λ„£κΈ°

            this.adjacencyList[currentVertex].forEach(neighbor => {
               if(!visited[neighbor]){
                   visited[neighbor] = true; // λ°©λ¬Έλͺ©λ‘μ— λ„£κΈ°
                   stack.push(neighbor) // μŠ€νƒμ— λ„£κ³ 
               } 
            });
        }
        return result;
    }
}

22.3 λ„ˆλΉ„ μš°μ„  κ·Έλž˜ν”„ 순회(BFS)

  λ„ˆλΉ„ μš°μ„  κ·Έλž˜ν”„ μˆœνšŒλŠ” 주어진 정점에 λŒ€ν•΄μ„œ λͺ¨λ“  인접점을 λ‹€ λ°©λ¬Έν•œ λ‹€μŒμ— μΈμ ‘μ μ˜ 인접점을 λ°©λ¬Έν•˜λŠ” λ°©μ‹μœΌλ‘œ μˆœνšŒν•œλ‹€. 즉, ν•˜λ‚˜μ˜ μ •μ μ—μ„œ μ‹œμž‘ν•˜κ³  κ·Έ μ‹œμž‘ν•˜λŠ” 정점과 μ—°κ²°λ˜μ–΄ μžˆλŠ” λͺ¨λ“  정점듀을 λ‹€ λ°©λ¬Έν•œ 후에 μ •μ μ˜ μ •μ μœΌλ‘œ μ΄λ™ν•˜μ—¬ 같은 μž‘μ—…μ„ λ°˜λ³΅ν•΄μ„œ μˆœνšŒν•œλ‹€. 

 

β—Žμˆ˜λ„μ½”λ“œ

λ°˜λ³΅ν˜• DFS와 거의 μœ μ‚¬ν•˜μ§€λ§Œ λ‹€λ₯Έ 점은 μŠ€νƒμ΄ μ•„λ‹Œ 큐λ₯Ό μ‚¬μš©ν•΄μ„œ κ΅¬ν˜„ν•˜λŠ” 것이닀.

1) ν•¨μˆ˜λŠ” μ‹œμž‘ν•  정점을 인수둜 λ°›κ³ , 큐 배열을 λ§Œλ“ λ‹€.

2) 그리고 μ‹œμž‘ν•  정점을 큐 배열에 μΆ”κ°€ν•œλ‹€.

3) 그리고 결과둜 λ°˜ν™˜ν•  배열을 λ§Œλ“€μ–΄ μˆœνšŒν•œ 정점듀을 μΆ”κ°€ν•˜κ³  λ§ˆμ§€λ§‰μ— λ°˜ν™˜ν•΄ μ€€λ‹€.(κ²°κ³Ό λ°°μ—΄)

4) 이미 λ°©λ¬Έν•œ 정점듀을 μ €μž₯ν•˜κΈ° μœ„ν•΄ 객체λ₯Ό λ§Œλ“€κ³  μ‹œμž‘ 정점을 λ°©λ¬Έν•œ κ²ƒμœΌλ‘œ ν‘œμ‹œν•œλ‹€.(λ°©λ¬Έ 객체)

5) 큐 μ•ˆμ— 정점이 λ“€μ–΄κ°€ μžˆλŠ”ν•œ while 루프λ₯Ό 톡해 λ°˜λ³΅ν•˜κ³  shift λ©”μ„œλ“œλ₯Ό 톡해 λ°°μ—΄μ˜ κ°€μž₯ μ•žμ— μžˆλŠ” λ…Έλ“œλ₯Ό λΉΌλ‚Έλ‹€.

6) 그리고 κ²°κ³Ό 배열에 μΆ”κ°€ν•΄ μ€€λ‹€.

7) 그리고 ν•΄λ‹Ή 점점에 μžˆλŠ” 각 인접점듀에 λŒ€ν•΄ 아직 λ°©λ¬Έν•˜μ§€ μ•Šμ•˜λ‹€λ©΄ λ°©λ¬Έν•œ κ²ƒμœΌλ‘œ ν‘œμ‹œν•˜κ³  큐에 μΆ”κ°€ν•΄μ€€ λ‹€μŒ κ²°κ³Ό 배열에 ν•˜λ‚˜μ”© λΉΌλ‚΄μ–΄ μΆ”κ°€ν•΄ μ€€λ‹€.

class Graph{
    constructor(){
        this.adjacencyList = {};
    }
    addVertex(vertex){
        if(!this.adjacencyList[vertex]) this.adjacencyList[vertex] = [];
    }
    addEdge(v1,v2){
        this.adjacencyList[v1].push(v2);
        this.adjacencyList[v2].push(v1);
    }
    removeEdge(vertex1,vertex2){
        this.adjacencyList[vertex1] = this.adjacencyList[vertex1].filter(
            v => v !== vertex2
        );
        this.adjacencyList[vertex2] = this.adjacencyList[vertex2].filter(
            v => v !== vertex1
        );
    }
    removeVertex(vertex){
        while(this.adjacencyList[vertex].length){
            const adjacentVertex = this.adjacencyList[vertex].pop();
            this.removeEdge(vertex, adjacentVertex);
        }
        delete this.adjacencyList[vertex]
    }

    breadthFirst(start){
        const queue = [start];
        const result = [];
        const visited = {};
        let currentVertex;
        visited[start] = true;

        while(queue.length){
            currentVertex = queue.shift();
            result.push(currentVertex);
           

            this.adjacencyList[currentVertex].forEach(neighbor => {
                if(!visited[neighbor]){
                    visited[neighbor] = true;
                    queue.push(neighbor);
                }
            });
        }
        return result;
    }
}

 

'πŸ“š Language & CS knowledge > Algorithm & Data structure' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

23 동적 ν”„λ‘œκ·Έλž˜λ°  (0) 2022.08.21
20 κ·Έλž˜ν”„  (0) 2022.08.17
19 ν•΄μ‹œ ν…Œμ΄λΈ”  (0) 2022.08.16
18 이진 νž™  (0) 2022.08.16
17 트리 순회  (0) 2022.08.16