๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿชฒ debug

Data Structures & Algorithms with Javascript : Graphs and Graph Algorithms

2024.07.25 - [๐Ÿค– data structures & algorithms] - Data Structures & Algorithms with Javascript : Binary Trees and Binary Search Trees

 

Data Structures & Algorithms with Javascript : Binary Trees and Binary Search Trees

2024.07.24 - [๐Ÿค– data structures & algorithms] - Data Structures & Algorithms with Javascript : Sets Data Structures & Algorithms with Javascript : Sets[์ด์ „ ๊ธ€]2024.07.23 - [๐Ÿค– data structures & algorithms] - Data Structures & Algorithms with Java

pyotato-dev.tistory.com

์˜ค๋Š˜์€ ๊ทธ๋ž˜ํ”„๋กœ ๋„คํŠธ์›Œํฌ๊ฐ€ ๋ชจ๋ธ๋ง ๋˜๋Š” ๋ฐฉ์‹, ๊ทธ๋ž˜ํ”„๊ฐ€ ๋ฌด์—‡์ธ์ง€, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ๊ตฌํ˜„ ๋“ฑ์— ๋Œ€ํ•ด ์‚ดํŽด๋ณด์ž.

โ€ผ ์˜ˆ์ œ๋Š” ์ฑ…์˜ ๊ตฌํ˜„์„ ์ฐธ๊ณ ํ•˜์—ฌ ํด๋ž˜์Šค๋กœ ์žฌ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค!!

๐Ÿ•ธ๏ธ ๊ทธ๋ž˜ํ”„๋ž€?

๊ทธ๋ž˜ํ”„๋Š” vertice(vertex์˜ ๋ณต์ˆ˜ํ˜•)์™€ edge๋กœ ๊ตฌ์„ฑ๋œ๋‹ค. 

๊ทธ๋ž˜ํ”„์˜ ๊ฐœ๋…์„ ๊ฐ•๋‚จ๊ตฌ ์ง€๋„์— ๋Œ€์ž…ํ•ด๋ณด์ž๋ฉด vertice๋Š” ๊ฐ•๋‚จ์—ญ, ์—ญ์‚ผ์—ญ, ์‚ผ์„ฑ์—ญ ๋“ฑ๋“ฑ์˜ ์—ญ์ด๊ณ ,

๊ฐ ์—ญ์„ ์—ฐ๊ฒฐํ•˜๊ณ  ์žˆ๋Š” 2ํ˜ธ์„  ์ง€ํ•˜์ฒ ์ด edge์— ํ•ด๋‹น๋œ๋‹ค.

๊ฐ•๋‚จ์—ญ(v1)์—์„œ ์‚ผ์„ฑ์—ญ(v2)์œผ๋กœ ๊ฐ€๋Š” ์ง€ํ•˜์ฒ  ๋…ธ์„ ๋„ ์žˆ๊ฒ ์ง€๋งŒ ๋ฒ„์Šค๋ฅผ ํƒ€๊ณ  ๊ฐˆ ์ˆ˜๋„ ์žˆ๊ณ , ๊ฑธ์–ด๊ฐ€๋Š” ๊ธธ๋„ ์žˆ์„ ์ˆ˜๋„ ์žˆ๋‹ค.

๊ฐ€๋Š” ๋ฐฉ๋ฒ•์— ๋”ฐ๋ผ ๋น„์šฉ์ด๋‚˜ ์‹œ๊ฐ„์ด ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๋Š”๋ฐ, ๊ทธ๋ž˜ํ”„์—์„œ๋Š” ์ด ๋น„์šฉ์„ weight (cost) ๋ผ๊ณ  ํ•œ๋‹ค.

๊ฐ•๋‚จ์—ญ(v1)์—์„œ ์‚ผ์„ฑ์—ญ(v2)์œผ๋กœ ์ด์–ด์ง€๋Š” edge๋ฅผ pair(v1, v2)๋กœ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

vertice๋“ค์„ ์—ฐ๊ฒฐํ•˜๋Š” edge๋“ค์„ path๋ผ๊ณ  ํ•˜๋Š”๋ฐ, ์ž๊ธฐ ์ž์‹ ์˜ vertex๋กœ ์—ฐ๊ฒฐ๋œ path๋Š” loop๋ผ๊ณ  ํ•œ๋‹ค. 

ํ•˜๋‚˜์˜ vertex์—์„œ ๋‹ค๋ฅธ vertex๊นŒ์ง€๋ฅผ path์˜ ๊ธธ์ด(length)๋ผ๊ณ  ํ•˜๊ณ , loop์˜ path ๊ธธ์ด๋Š” 0์ด๋‹ค.

์•„๋ž˜์˜ ์ง€๋„๋Š” ์ถœ๋ฐœ ์ง€์ ๊ณผ ๋„์ฐฉ์ง€์ ์ด ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๋ฐฉํ–ฅ์ด ์žˆ๋Š” ๊ทธ๋ž˜ํ”„๋Š” directed graph (digraph)๋ผ๊ณ  ํ•œ๋‹ค. 

๋ฐ˜๋ฉด์— ๋ฐฉํ–ฅ์ด ์—†๋Š” ๊ทธ๋ž˜ํ”„๋Š” unordred graph (graph)๋ผ๊ณ  ํ•œ๋‹ค.

๊ฐ•๋‚จ์—ญ์—์„œ ์‚ผ์„ฑ์—ญ๊นŒ์ง€์˜ ์ง€๋„

 

digraph ์™€ graph

 

๋‘ vertice ์‚ฌ์ด์— path๊ฐ€ ์žˆ๋‹ค๋ฉด strongly connected๋ผ๊ณ  ํ‘œํ˜„ํ•œ๋‹ค.

 

๐Ÿ—บ๏ธ ๊ทธ๋ž˜ํ”„ ๊ตฌํ˜„

์–ธ๋œป๋ณด๋ฉด ๊ทธ๋ž˜ํ”„ ๊ตฌ์กฐ๊ฐ€ ํŠธ๋ฆฌ๋‚˜ ์ด์ง„ํŠธ๋ฆฌ์™€ ๋น„์Šทํ•ด ๋ณด์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ vertex๋ฅผ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด Node ํด๋ž˜์Šค๋กœ ๋‚˜ํƒ€๋‚ด๋ ค๊ณ  ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ Node ํด๋ž˜์Šค์™€ ๊ฐ™์€ ๊ฐ์ฒด ๊ธฐ๋ฐ˜์˜ ์ ‘๊ทผ์€ ๊ทธ๋ž˜ํ”„์˜ ํฌ๊ธฐ๊ฐ€ ์ปค์ง์— ๋”ฐ๋ผ ๋ถ€์ ํ•ฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด์ง„ํŠธ๋ฆฌ๋Š” ์ž์‹ ๋…ธ๋“œ์˜ ๊ฐœ์ˆ˜๊ฐ€ 2๊ฐœ ์ดํ•˜๋กœ ์ œํ•œ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋…ธ๋“œ ๊ฐ„์˜ ์—ฐ๊ฒฐ์ด ๋ฌดํ•œํ•  ์ˆ˜ ์žˆ๋Š” ๊ทธ๋ž˜ํ”„๋ฅผ ํ‘œํ˜„ํ•˜๊ธฐ์—๋Š” ์–ด๋ ค์›€์ด ์žˆ๋‹ค.

๊ทธ๋Ÿผ ์–ด๋–ค ์ž๋ฃŒ ๊ตฌ์กฐ๋กœ vertice์™€ edge๋ฅผ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์„๊นŒ?

Vertex ๊ตฌํ˜„

Graph ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ๊ทธ๋ž˜ํ”„๋ฅผ ๊ตฌ์„ฑํ•  Vertex๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ์™€ linked list์—์„œ ์‚ดํŽด๋ดค๋˜ ๊ฒƒ์ฒ˜๋Ÿผ Node ํด๋ž˜์Šค๋Š” Vertex์™€ ๋น„์Šทํ•œ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•ด์•ผํ•œ๋‹ค.

Vertex๊ฐ€ ์ง€๋…€์•ผ ํ•  ์ •๋ณด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค

  1. label : vertex์˜ ๊ฐ’
  2. wasVisited : vertex ๋ฐฉ๋ฌธ ์—ฌ๋ถ€
class Vertex{
	constructor(label){
		this.label = label;
	}
}

Edge ๊ตฌํ˜„

์ธ์ ‘ ๋ฆฌ์ŠคํŠธ (adjacency list ๋˜๋Š” array of adjacency lists)

๋‘ ๊ฐœ์˜ ๋ฐฐ์—ด์„ ํ™œ์šฉํ•œ๋‹ค. ๊ฐ ๋ฐฐ์—ด์˜ ์ธ๋ฑ์Šค๊ฐ€ vertice๋ฅผ ๋‚˜ํƒ€๋‚ด๊ณ , ๊ฐ ๋ฐฐ์—ด์˜ ๊ฐ’์€ ๊ทธ vertice๊ฐ€ ์—ฐ๊ฒฐ๋œ vetice๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.

์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ทธ๋ž˜ํ”„๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•˜์ž. vertice 2๋Š” ๋‚˜๋จธ์ง€ 0,1,3,4์™€ ์—ฐ๊ฒฐ๋œ edge๋“ค์ด ์žˆ๋‹ค.

 

์ธ์ ‘ ๋ฆฌ์ŠคํŠธ๋ฅผ ํ™œ์šฉํ•ด์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์—ฐ๊ฒฐ ๊ด€๊ณ„๋ฅผ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

vertex ์ธ๋ฑ์Šค 0์—๋Š” vertex ์ธ๋ฑ์Šค 2๊ฐ€, ์ธ๋ฑ์Šค 1์—๋Š” 2๊ฐ€ ์ธ๋ฑ์Šค 2๋Š” 0,1,3,4๊ฐ€, ์ธ๋ฑ์Šค 3์€ ์ธ๋ฑ์Šค 2๊ฐ€, ๊ทธ๋ฆฌ๊ณ  ์ธ๋ฑ์Šค 4๋Š” 2๋ฅผ ๋ฐฐ์—ด ์›์†Œ๋กœ ์ง€๋‹ ์ˆ˜ ์žˆ๋‹ค.

 

์ธ์ ‘ ๋ฆฌ์ŠคํŠธ

 

์ธ์ ‘ ํ–‰๋ ฌ (adjacency matrix)

์ด์ฐจ์› ๋ฐฐ์—ด๋กœ ๋‘ vertice ์‚ฌ์ด์— edge๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฐฉ์‹์œผ๋กœ๋„ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

vertex ์‚ฌ์ด์— edge๊ฐ€ ์กด์žฌํ•˜๋ฉด true(1), ์•„๋‹ˆ๋ฉด false(0) 

    0,  1,  2,  3,  4
0 [0,  0,  1,  0,  0]
1 [0,  0,  1,  0,  0]
2 [1,  1,  0,  1,  1]
3 [0,  0,  1,  0,  0]
4 [0,  0,  1,  0,  0]

๊ทธ๋ž˜ํ”„ ๊ตฌํ˜„

์šฐ๋ฆฌ๋Š” ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ๋กœ ๊ทธ๋ž˜ํ”„๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด์ž.

class Graph {
	constructor(v){
    	this.vertices = v; 
        this.edges = 0;
        this.adj = [];	// ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ๋กœ ๊ตฌํ˜„
        for(let i=0; i<this.vertices;++i){
        	this.adj[i] = [];
        }
    }
    
    // ์ถœ๋ ฅ ํ—ฌํผ ํ•จ์ˆ˜
    print(item){
		console.log(item);
	}
    
    // edge ์ถ”๊ธฐ
	addEdge(v,w){
    	this.adj[v].push(w);
        this.adj[w].push(v);
        this.edges++;
    }
	
    // ๊ทธ๋ž˜ํ”„ ๊ทธ๋ฆฌ๊ธฐ
    showGraph(){
    	for(let i=0; i< this.vertices; ++i){
            this.print(`${i} -> ${this.adj[i].join(', ')}`);
        }
    }
}

const graph = new Graph(5);
graph.addEdge(0,1);
graph.addEdge(0,2);
graph.addEdge(1,3);
graph.addEdge(2,4);
graph.showGraph();

/**
0 -> 1, 2
1 -> 0, 3
2 -> 0, 4
3 -> 1
4 -> 2

*/

๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰

๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰ ์•Œ๊ณ ๋ฆฌ์ฆ˜์—๋Š” ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค : DFS(depth-first-search)์™€ BFS (breadth-first search)

 

dfs์™€ bfs

DFS (๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰)

dfs๋Š” ์‹œ์ž‘ํ•˜๋Š” vertex์—์„œ ๋งˆ์ง€๋ง‰ vertex์— ๋„๋‹ฌํ•  ๋•Œ๊นŒ์ง€ ํƒ์ƒ‰ํ•˜๊ณ ,

๋ vertex์—์„œ ์—ญ์œผ๋กœ ๊ฑฐ์Šฌ๋Ÿฌ (backtrack) ์˜ฌ๋ผ์™€์„œ ๋” ์ด์ƒ ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์€ vertex๊ฐ€ ์—†์„ ๋•Œ๊นŒ์ง€ ๋‹ค์Œ path์„ ํƒ์ƒ‰ํ•œ๋‹ค.

dfs

dfs ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ตฌํ˜„ ๋กœ์ง์€ ๊ฐ„๋‹จํ•œ ํŽธ์ด๋‹ค. ์•„์ง ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์€ vertex๋“ค์„ ๋ฐฉ๋ฌธํ•˜๊ณ  ๋ฐฉ๋ฌธ์—ฌ๋ถ€๋ฅผ ๋งˆํฌํ•˜๋ฉด ๋œ๋‹ค.

๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์€ vertex๊ฐ€ ์—†์„ ๋•Œ๊นŒ์ง€ ์žฌ๊ท€์ ์œผ๋กœ ํƒ์ƒ‰์„ ํ•˜๋ฉด ๋œ๋‹ค.

 

๊ตฌํ˜„

 

class Graph {
	constructor(v){
    	this.vertices = v; 
        this.edges = 0;
        this.adj = [];	
        for(let i=0; i<this.vertices;++i){
        	this.adj[i] = [];
        }
        /////////////////////////// ๐Ÿ’–์ˆ˜์ • ///////////////////////////
        this.visited = [];	
        for(let i=0; i<this.vertices;++i){
        	this.visited[i] = false;
        }
        /////////////////////////// ๐Ÿ’–์ˆ˜์ • ///////////////////////////
    }
    
    // ์ถœ๋ ฅ ํ—ฌํผ ํ•จ์ˆ˜
    print(item){
		console.log(item);
	}
    
    // edge ์ถ”๊ธฐ
	addEdge(v,w){
    	this.adj[v].push(w);
        this.adj[w].push(v);
        this.edges++;
    }
	
    // ๊ทธ๋ž˜ํ”„ ๊ทธ๋ฆฌ๊ธฐ
    showGraph(){
    	for(let i=0; i< this.vertices; ++i){
            this.print(`${i} -> ${this.adj[i].join(', ')}`);
        }
    }
    /////////////////////////// ๐Ÿ’–์ถ”๊ฐ€ ///////////////////////////
    // dfs 
    dfs(v){
    	this.visited[v] = true;
        if(this.adj[v] != undefined){
        	this.print(`visited vertex: ${v}`);
        }
        this.adj[v].forEach((w)=>{
            if(!this.visited[w]){
                this.dfs(w);
            }
        })
    }
    /////////////////////////// ๐Ÿ’–์ถ”๊ฐ€ ///////////////////////////
}

const graph = new Graph(5);
graph.addEdge(0,1);
graph.addEdge(0,2);
graph.addEdge(1,3);
graph.addEdge(2,4);
graph.showGraph();
graph.dfs(0);

/**
0 -> 1, 2
1 -> 0, 3
2 -> 0, 4
3 -> 1
4 -> 2
visited vertex: 0
visited vertex: 1
visited vertex: 3
visited vertex: 2
visited vertex: 4
*/

 

BFS (๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰)

bfs

 

bfs๋Š” ์ฒซ vertex์—์„œ ์‹œ์ž‘ํ•ด์„œ ๊ฐ€๋Šฅํ•œ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด vertex๋ฅผ ์ฐพ์•„ ๋ฐฉ๋ฌธํ•œ๋‹ค. 

ํ•˜๋‚˜์˜ path์„ ๋”ฐ๋ผ ๋งˆ์ง€๋ง‰ vertex์— ๋ฐฉ๋ฌธํ•˜๋ ค๋Š” dfs์™€๋Š” ๋‹ฌ๋ฆฌ bfs๋Š” layer ๋‹จ์œ„๋กœ ๋จผ์ € ๋ฐฉ๋ฌธํ•œ๋‹ค.

์œ„์˜ ๊ทธ๋ฆผ์—์„œ k, h, e, b๋Š” ๊ฐ™์€ layer์—, c, f, i, l๋„ ๊ฐ™์€ layer๋‹ค. bfs๋Š” ์ฒซ vertex์ธ a๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ ๊ฐ€๊นŒ์šด layer๋“ค์˜ vertex๋“ค์„ ๋ฐฉ๋ฌธํ•œ๋‹ค. bfs๋Š” vertice ๋ฐฉ๋ฌธ์„ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด  queue๋ฅผ ์ถ”์ƒํ™”ํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ํ™œ์šฉํ•œ๋‹ค.

์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋กœ์ง์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  1. ํ˜„์žฌ vertex์™€ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์€ vertex๋ฅผ ์ฐพ์•„ ๋ฐฉ๋ฌธํ•œ vertice ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€ํ•˜๊ณ  queue์—๋„ ์ถ”๊ฐ€ํ•œ๋‹ค.
  2. ๋‹ค์Œ vertex v๋ฅผ  ๊ทธ๋ž˜ํ”„์—์„œ ๊ฐ€์ ธ์™€ ๋ฐฉ๋ฌธํ•œ vertice ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€ํ•œ๋‹ค.
  3. v์™€ ์ธ์ ‘ํ•œ ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์€ vertice๋ฅผ ๋ชจ๋‘ queue์— ์ถ”๊ฐ€ํ•œ๋‹ค.
class Graph {
	constructor(v){
    	this.vertices = v; 
        this.edges = 0;
        this.adj = [];	
        for(let i=0; i<this.vertices;++i){
        	this.adj[i] = [];
        }
        this.visited = [];	
        for(let i=0; i<this.vertices;++i){
        	this.visited[i] = false;
        }
    }
    
    // ์ถœ๋ ฅ ํ—ฌํผ ํ•จ์ˆ˜
    print(item){
		console.log(item);
	}
    
    // edge ์ถ”๊ธฐ
	addEdge(v,w){
    	this.adj[v].push(w);
        this.adj[w].push(v);
        this.edges++;
    }
	
    // ๊ทธ๋ž˜ํ”„ ๊ทธ๋ฆฌ๊ธฐ
    showGraph(){
    	for(let i=0; i< this.vertices; ++i){
            this.print(`${i} -> ${this.adj[i].join(', ')}`);
        }
    }
    
    // dfs 
    dfs(v){
    	this.visited[v] = true;
        if(this.adj[v] != undefined){
        	this.print(`visited vertex: ${v}`);
        }
        this.adj[v].forEach((w)=>{
            if(!this.visited[w]){
                this.dfs(w);
            }
        })
    }
    
    /////////////////////////// ๐Ÿ’–์ถ”๊ฐ€ ///////////////////////////
    // bfs 
    bfs(s){
    	let queue = [];
    	this.visited[s] = true;
        queue.push(s);	// ๋งจ ๋’ค์— ์ถ”๊ฐ€
        while(queue.length>0){
        	let v = queue.shift(); // ๋งจ ์•ž์—์„œ ๊บผ๋‚ด์˜ค๊ธฐ
            if(v != null){
            	this.print(`visited vertex : ${v}`);
            }
            this.adj[v].forEach((w)=>{
                if(!this.visited[w]){
                    this.visited[w]= true;
					queue.push(w);
                }
       		})
        }

    }
    /////////////////////////// ๐Ÿ’–์ถ”๊ฐ€ ///////////////////////////
}

const graph = new Graph(5);
graph.addEdge(0,1);
graph.addEdge(0,2);
graph.addEdge(1,3);
graph.addEdge(2,4);
graph.showGraph();
graph.bfs(0);

/**
0 -> 1, 2
1 -> 0, 3
2 -> 0, 4
3 -> 1
4 -> 2
visited vertex: 0
visited vertex: 1
visited vertex: 3
visited vertex: 2
visited vertex: 4
*/

 

dfs bfs ๋น„๊ต

๊ทธ๋ž˜ํ”„๋กœ ๋‚˜ํƒ€๋‚ด๊ธฐ

0 -> 1, 2
1 -> 0, 3
2 -> 0, 4
3 -> 1
4 -> 2

                  3๏ธโƒฃ        
           b   ⁄
          1๏ธโƒฃ 
  a   ⁄
0๏ธโƒฃ   
       ๏ผผ  c
           2๏ธโƒฃ
                 ๏ผผ   d
                     4๏ธโƒฃ

dfs 
vertex ๋ฐฉ๋ฌธ ์ˆœ์„œ : 0 1 3 2 4
                 edge :   a b c d 

bfs
vertex ๋ฐฉ๋ฌธ ์ˆœ์„œ : 0 1 2 3 4
                   edge :   a c b d 

์ตœ๋‹จ ๊ฑฐ๋ฆฌ ๊ตฌํ•˜๊ธฐ 

๊ทธ๋ž˜ํ”„ ์—ฐ์‚ฐ ์ค‘ ๊ฐ€์žฅ ํ”ํ•˜๊ฒŒ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์€ ๋‘ vertex ๊ฐ„์˜ ์ตœ๋‹จ ๊ฑฐ๋ฆฌ๋ฅผ ๊ตฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์ด๋ฏธ์ง€ ์ถœ์ฒ˜ : https://m.blog.naver.com/hoti7746/223029389423

 

๐Ÿ๏ธ ์œ ๋Ÿฝ์œผ๋กœ ํœด๊ฐ€๋ฅผ ๊ฐ„๋‹ค๊ณ  ์ƒ๊ฐํ•ด ๋ณด์ž.

ํŒŒ๋ฆฌ, ์Šค์œ„์Šค ์˜ค์ŠคํŠธ๋ฆฌ์•„, ๋ฒ ๋„ค์น˜์•„, ํ”Œ๋กœ๋ Œ์Šค, ๋กœ๋งˆ๋ฅผ ๋ชจ๋‘ ๋ฐฉ๋ฌธํ•˜๊ณ  ์‹ถ์€๋ฐ

2์ฃผ ์•ˆ์— ์ตœ๋Œ€ํ•œ ์ ์€ ๊ฑฐ๋ฆฌ๋กœ ๋ฐฉ๋ฌธํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ๋ญ˜๊นŒ?

์ตœ๋‹จ ๊ฑฐ๋ฆฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ํ™œ์šฉํ•ด ๋ณธ๋‹ค๋ฉด ๊ฐ€์•ผ ํ•˜๋Š” ๊ฑฐ๋ฆฌ๋ฅผ ์ตœ์†Œํ™”ํ•ด ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

 

 

BFS๋กœ ์ตœ๋‹จ ๊ฑฐ๋ฆฌ ์ฐพ๊ธฐ

 

bfs์˜ ๊ฒฝ์šฐ ์ž๋™์œผ๋กœ ํ•˜๋‚˜์˜ vertex์—์„œ ๋‹ค๋ฅธ vertex๋กœ ๊ฐ€๋Š” ์ตœ๋‹จ ๊ฑฐ๋ฆฌ๋ฅผ ์ฐพ๊ฒŒ ๋œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด A vertex์—์„œ D๋กœ ๊ฐ€๋Š” ์ตœ๋‹จ ๊ฑฐ๋ฆฌ๋ฅผ ๊ตฌํ•  ๋•Œ, ๋‘ vertex๋กœ ๊ฐ€๋Šฅ edge๊ฐ€ 1๊ฐœ์ธ ๊ฒฝ์šฐ๋ถ€ํ„ฐ ๊ทธ๋‹ค์Œ์—๋Š” 2๊ฐœ์ธ ๊ฒฝ์šฐ ๊ทธ๋‹ค์Œ์€ 3๊ฐœ... ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ๊ฑฐ๋ฆฌ๋ฅผ ๊ตฌํ•œ๋‹ค. bfs๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹๊ณผ ๋™์ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— bfs๋ฅผ ์กฐ๊ธˆ ์ˆ˜์ •ํ•ด์„œ ์ตœ๋‹จ ๊ฑฐ๋ฆฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ตฌํ˜„ํ•ด ๋ณด์ž.

class Graph {
    constructor(v){
        this.vertices = v; 
        this.edges = 0;
        this.adj = [];    
        for(let i=0; i<this.vertices; ++i){
            this.adj[i] = [];
        }
        this.visited = [];    
        for(let i=0; i<this.vertices; ++i){
            this.visited[i] = false;
        }
        this.edgeTo = [];
    }
    
    // ์ถœ๋ ฅ ํ—ฌํผ ํ•จ์ˆ˜
    print(item){
        console.log(item);
    }
    
    // edge ์ถ”๊ฐ€
    addEdge(v, w){
        this.adj[v].push(w);
        this.adj[w].push(v);
        this.edges++;
    }
    
    // ๊ทธ๋ž˜ํ”„ ๊ทธ๋ฆฌ๊ธฐ
    showGraph(){
        for(let i=0; i< this.vertices; ++i){
            this.print(`${i} -> ${this.adj[i].join(', ')}`);
        }
    }
    
    // dfs 
    dfs(v){
        this.visited[v] = true;
        if(this.adj[v] != undefined){
            this.print(`visited vertex: ${v}`);
        }
        this.adj[v].forEach((w)=>{
            if(!this.visited[w]){
                this.dfs(w);
            }
        });
    }
    
    // bfs 
    bfs(s){
        let queue = [];
        this.visited[s] = true;
        queue.push(s);    // ๋งจ ๋’ค์— ์ถ”๊ฐ€
        while(queue.length > 0){
            let v = queue.shift(); // ๋งจ ์•ž์—์„œ ๊บผ๋‚ด์˜ค๊ธฐ
            if(v != null){
                this.print(`visited vertex: ${v}`);
            }
            this.adj[v].forEach((w)=>{
                if(!this.visited[w]){
                    this.edgeTo[w] = v; 
                    this.visited[w] = true;
                    queue.push(w);
                }
            });
        }
    }
    /////////////////////////// ๐Ÿ’–์ถ”๊ฐ€ ///////////////////////////
    // ๋ฐฉ๋ฌธ ์—ฌ๋ถ€ ๋ฆฌํ„ด ํ—ฌํผ ํ•จ์ˆ˜
    hasPathTo(v) { 
        return this.visited[v];
    }
    
    // ์‹œ์ž‘์ ์—์„œ ๋ชฉ์ ์ง€๊นŒ์ง€์˜ path 
    pathTo(v){
        let source = 0;
        if(!this.hasPathTo(v)){
            return undefined;
        }
        let path = [];
        for(let i = v; i != source; i = this.edgeTo[i]){
            path.push(i);
        }
        path.push(source); // source๋ฅผ path์— ์ถ”๊ฐ€ 
        return path.reverse(); // source์—์„œ destination ๊นŒ์ง€์˜ path 
    }
    /////////////////////////// ๐Ÿ’–์ถ”๊ฐ€ ///////////////////////////
}

const graph = new Graph(5);
graph.addEdge(0,1);
graph.addEdge(0,2);
graph.addEdge(1,3);
graph.addEdge(2,4);

// 0๋ถ€ํ„ฐ bfs
graph.bfs(0);

let vertex = 4;
let paths = graph.pathTo(vertex);

if (paths) {
    let pathString = paths.join('-');
    graph.print(pathString);
} else {
    graph.print("No path found");
}

/**
Expected output:
0-2-4
*/

Topological Sorting  (์œ„์ƒ ์ •๋ ฌ)

์œ„์ƒ์ •๋ ฌ์€ ๋ฐฉํ–ฅ์ด ์žˆ๋Š” ๊ทธ๋ž˜ํ”„์˜ vertice๋“ค์„ ์ •๋ ฌํ•œ ๊ฑด๋ฐ, ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋Š” vertice๋“ค์ด ์—†๋‹ค๋ฉด ๋จผ์ € ์œ„์น˜์‹œํ‚ค๊ณ , ๋‹ค๋ฅธ vertex๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋Š” vertex๋“ค์€ ๋ชจ๋‘ ์ดํ›„์— ์ •๋ ฌํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

์ปดํ“จํ„ฐ ๊ณผํ•™ ํ•™์Šต ์ปค๋ฆฌํ˜๋Ÿผ ์œ„์ƒ์ •๋ ฌ

์œ„์ƒ ์ •๋ ฌ์„ ํ•˜๋ฉด ๊ทธ๋ž˜ํ”„๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  1. CS1
  2. CS2
  3. Assembly language
  4. Data structures
  5. Operating systems
  6. Algorithms

3๋ฒˆ ์ˆ˜์—… (Assembly language)์™€ 4๋ฒˆ ์ˆ˜์—…(Data structure)์€ ๋™์‹œ์— ์ˆ˜๊ฐ•์ด ๊ฐ€๋Šฅํ•˜๊ณ , 5๋ฒˆ ์ˆ˜์—… (Operating systems)์™€ 6๋ฒˆ ์ˆ˜์—…(Algorithms)๋„ ๋™์‹œ์— ์ˆ˜๊ฐ•์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ํ•˜์ง€๋งŒ CS2๋ฅผ ์ˆ˜๊ฐ•ํ•˜์ง€ ์•Š๊ณ ์„œ๋Š” Data structures๋ฅผ ์ˆ˜๊ฐ•ํ•  ์ˆ˜๋Š” ์—†๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ precedence-constrained scheduling๋ผ๊ณ  ํ•œ๋‹ค. 

 

์œ„์ƒ ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ dfs์™€ ๋น„์Šทํ•˜๋‹ค. ํ•˜์ง€๋งŒ ๋ฐฉ๋ฌธํ•œ vertex๋ฅผ ๋ฐ”๋กœ ์ถœ๋ ฅํ•˜๋Š” ๋Œ€์‹ 

ํ˜„์žฌ vertex์™€ ์ธ์ ‘ํ•œ vertice๋ฅผ ๋ชจ๋‘ ๋ฐฉ๋ฌธํ•˜๊ณ  ๋‚˜์„œ ํ˜„์žฌ vertex๋ฅผ ์Šคํƒ์— ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

 

์œ„์ƒ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋‘ ๊ฐœ์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ํ•ต์‹ฌ์ด๋‹ค.

  • topSort : ์ •๋ ฌ ๊ณผ์ •์„ ํ•˜๋Š” topSortHelper๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ํ—ฌํผ ํ•จ์ˆ˜
  • topSortHelper : ์ •๋ ฌ๋œ vertice๋“ค ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ณด์—ฌ์ค€๋‹ค.  ํ˜„์žฌ vertex๋ฅผ ๋ฐฉ๋ฌธ ์ฒ˜๋ฆฌํ•˜๊ณ  ์žฌ๊ท€์ ์œผ๋กœ ํ˜„์žฌ vertex์˜ ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ์— ์ธ์ ‘ํ•œ vertex๋ฅผ ๋ฐฉ๋ฌธํ•˜๊ณ  ๋ฐฉ๋ฌธ์ฒ˜๋ฆฌ๋ฅผ ํ•œ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ ํ˜„์žฌ vertex๋ฅผ ์Šคํƒ์— ์ถ”๊ฐ€ํ•œ๋‹ค.
class Graph {
    constructor(v){
        this.vertices = v; 
        this.edges = 0;
        this.adj = [];    
        for(let i = 0; i < this.vertices; ++i){
            this.adj[i] = [];
        }
        this.visited = [];    
        for(let i = 0; i < this.vertices; ++i){
            this.visited[i] = false;
        }
        this.edgeTo = [];
        this.vertexList = [];
    }
    
    print(item){
        console.log(item);
    }
    
    addEdge(v, w){
        this.adj[v].push(w);
        this.edges++;
    }

    addVertex(v){
        this.vertexList.push(v);
    }
    
    showGraph(){
        for(let i = 0; i < this.vertices; ++i){
            this.print(`${this.vertexList[i]} -> ${this.adj[i].map(v => this.vertexList[v]).join(', ')}`);
        }
    }
    
    dfs(v){
        this.visited[v] = true;
        if(this.adj[v] != undefined){
            this.print(`visited vertex: ${this.vertexList[v]}`);
        }
        this.adj[v].forEach((w) => {
            if(!this.visited[w]){
                this.dfs(w);
            }
        });
    }
    
    
    bfs(s){
        let queue = [];
        this.visited[s] = true;
        queue.push(s);    
        while(queue.length > 0){
            let v = queue.shift(); 
            if(v != null){
                this.print(`visited vertex: ${this.vertexList[v]}`);
            }
            this.adj[v].forEach((w) => {
                if(!this.visited[w]){
                    this.edgeTo[w] = v; 
                    this.visited[w] = true;
                    queue.push(w);
                }
            });
        }
    }

    // vertex๋กœ ๊ฐ€๋Š” path ์žˆ๋Š” ์ง€ ํ™•์ธํ•˜๋Š” ํ—ฌํผ ํ•จ์ˆ˜
    hasPathTo(v) { 
        return this.visited[v];
    }
    
    // vertex๋กœ๊ฐ€๋Š” path ๊ตฌํ•˜๊ธฐ
    pathTo(v){
        let source = 0;
        if(!this.hasPathTo(v)){
            return undefined;
        }
        let path = [];
        for(let i = v; i != source; i = this.edgeTo[i]){
            path.push(i);
        }
        path.push(source); // source๋กœ๊ฐ€๋Š” path ์ถ”๊ฐ€
        return path.reverse(); // source์—์„œ destination ๊ฐ€๋Š” Path 
    }
     /////////////////////////// ๐Ÿ’–์ถ”๊ฐ€ ///////////////////////////
    // Topological sort
    topSort(){
        let stack = [];
        let visited = new Array(this.vertices).fill(false);
        for (let i = 0; i < this.vertices; i++) { 
            if (visited[i] == false) {
                this.topSortHelper(i, visited, stack); 
            }
        }
        while(stack.length > 0) {
            this.print(this.vertexList[stack.pop()]);
        }
    }
    
    topSortHelper(v, visited, stack) { 
        visited[v] = true;
        this.adj[v].forEach((w) => {
            if(!visited[w]){
                this.topSortHelper(w, visited, stack);
            }
        });
        stack.push(v);
    }
     /////////////////////////// ๐Ÿ’–์ถ”๊ฐ€ ///////////////////////////
}


const graph = new Graph(6);

graph.addVertex("CS1"); // 0
graph.addVertex("CS2"); // 1
graph.addVertex("Data Structures"); // 2
graph.addVertex("Assembly Language"); // 3
graph.addVertex("Operating Systems"); //4
graph.addVertex("Algorithms"); // 5

graph.addEdge(0, 1);
graph.addEdge(1, 2);
graph.addEdge(1, 3);
graph.addEdge(2, 4);
graph.addEdge(2, 5);

graph.topSort();

/**
CS1
CS2
Assembly Language
Data Structures
Algorithms
Operating Systems
*/

๐Ÿ“š Reference

- Data Structures and Algorithms Using Javaโ€ Script by Michael McMillian (O’Reilly). Copyright 2014 Michael McMillan, 978-1-449-36493-9