Data structures (with python) - 2. Graph - 2.1. Directed graph

2024. 1. 1. 22:41ใ†CS - Roadmap.sh/1. Data structures

Data structures (with python) - 2. Graph - 2.1. Directed graph

 

๐Ÿ’ก A directed graph is graph, i.e., a set of objects (called vertices or nodes) that are connected together, where all the edges are directed from one vertex to another. A directed graph is sometimes called a digraph or a directed network. In contrast, a graph where the edges are bidirectional is called an undirected graph.

 

๋ฐฉํ–ฅ์„ฑ ๊ทธ๋ž˜ํ”„๋Š” ์„œ๋กœ ์—ฐ๊ฒฐ๋œ ๊ฐ์ฒด(์ •์  ๋˜๋Š” ๋…ธ๋“œ๋ผ๊ณ  ํ•จ)์˜ ์ง‘ํ•ฉ์œผ๋กœ, ๋ชจ๋“  ๊ฐ€์žฅ์ž๋ฆฌ๊ฐ€ ํ•œ ์ •์ ์—์„œ ๋‹ค๋ฅธ ์ •์ ์œผ๋กœ ํ–ฅํ•˜๋Š” ๊ทธ๋ž˜ํ”„์ž…๋‹ˆ๋‹ค. ๋ฐฉํ–ฅ์„ฑ ๊ทธ๋ž˜ํ”„๋Š” ์ด์ค‘๊ทธ๋ž˜ํ”„(digraph) ๋˜๋Š” ๋ฐฉํ–ฅ์„ฑ ๋„คํŠธ์›Œํฌ๋ผ๊ณ ๋„ ๋ถˆ๋ฆฝ๋‹ˆ๋‹ค. ์ด์™€ ๋Œ€์กฐ์ ์œผ๋กœ, ๊ฐ€์žฅ์ž๋ฆฌ๊ฐ€ ์–‘๋ฐฉํ–ฅ์ธ ๊ทธ๋ž˜ํ”„๋ฅผ ๋ฌด๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

์ถœ์ฒ˜ : ์œ„ํ‚คํ”ผ๋””์•„
Oriented graph with corresponding incidence matrix

 

with python ์ด๋‹ˆ ํŒŒ์ด์ฌ์—์„œ ๋ฐฉํ–ฅ์„ฑ ๊ทธ๋ž˜ํ”„์— ๋Œ€ํ•ด ์•Œ์•„๋ด…์‹œ๋‹ค.

ํŒŒ์ด์ฌ์—์„œ ๋ฐฉํ–ฅ์„ฑ ๊ทธ๋ž˜ํ”„ (Directed Graph) ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ํƒ์ƒ‰ํ•˜๋Š” ๋ฐฉ๋ฒ•.

์ธ์ ‘ ๋ฆฌ์ŠคํŠธ(Adjacency List)์„ ์‚ฌ์šฉํ•ด์„œ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

(์ธ์ ‘๋ฆฌ์ŠคํŠธ ์ถ”ํ›„ ๋‹ค๋ฃจ๊ธฐ)

class DirectedGraph:
    def __init__(self):
        self.graph = {}

    def add_edge(self, node, neighbour):   
        if node not in self.graph:
            self.graph[node] = [neighbour]
        else:
            self.graph[node].append(neighbour)

 

๋จผ์ €, ๋ฐฉํ–ฅ์„ฑ ๊ทธ๋ž˜ํ”„๋ฅผ ์ €์žฅํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ด ํด๋ž˜์Šค๋Š” ๋…ธ๋“œ๋“ค์˜ ๋ชฉ๋ก์„ ์ €์žฅํ•˜๊ณ , ๋…ธ๋“œ๋“ค ๊ฐ„์˜ ์—ฐ๊ฒฐ ๊ด€๊ณ„๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

 

์œ„์˜ ์ฝ”๋“œ์—์„œ add_edge ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ๋…ธ๋“œ๊ฐ„์˜ ์—ฃ์ง€๋ฅผ ์ถ”๊ฐ€ํ• ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ฉ”์„œ๋“œ๋Š” ๋ฐฉํ–ฅ์„ฑ ์—ฃ์ง€๋ฅผ ํ‘œํ˜„ํ•˜๋ฏ€๋กœ, ๋…ธ๋“œ์—์„œ ์ด์›ƒ ๋…ธ๋“œ๋กœ๋งŒ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

 

๋‹ค์Œ์œผ๋กœ, ์ด ๊ทธ๋ž˜ํ”„๋ฅผ ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰(DFS)ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

DFS๋Š” ํ˜„์žฌ ๋…ธ๋“œ์—์„œ ๊ฐ€๋Šฅํ•œ ๊นŠ๊ฒŒ ํƒ์ƒ‰ํ•˜๊ณ , ๋” ์ด์ƒ ๋ฐฉ๋ฌธํ•  ๋…ธ๋“œ๊ฐ€ ์—†์„ ๋•Œ ์ด์ „ ๋…ธ๋“œ๋กœ ๋Œ์•„๊ฐ€๋Š” ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

(์ถ”ํ›„์— DFS, BFS๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค)

 

    def dfs(self, node, visited): # ์œ„ ์ฝ”๋“œ์™€ ์ด์–ด์ง‘๋‹ˆ๋‹ค ๋“ค์—ฌ์“ฐ๊ธฐ ์ฃผ์˜
        if node not in visited:
            visited.append(node)
            if node in self.graph:
                for neighbour in self.graph[node]:
                    self.dfs(neighbour, visited)
        return visited

 

์œ„์˜ ๋ฉ”์„œ๋“œ์—์„œ visited๋Š” ๋ฐฉ๋ฌธํ•œ ๋…ธ๋“œ๋“ค์˜ ๋ชฉ๋ก์„ ์ €์žฅํ•˜๋Š” ๋ฆฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค.

์žฌ๊ท€์ ์œผ๋กœ dfs๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๊ทธ๋ž˜ํ”„๋ฅผ ํƒ์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.

์ด ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐฉํ–ฅ์„ฑ ๊ทธ๋ž˜ํ”„๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํƒ์ƒ‰ํ•ด ๋ด…์‹œ๋‹ค.

 

g = DirectedGraph()
g.add_edge('A', 'B')
g.add_edge('A', 'C')
g.add_edge('B', 'D')
g.add_edge('C', 'D')

print(g.dfs('A', []))  # ['A', 'B', 'D', 'C']

 

์œ„์˜ ์ฝ”๋“œ์—์„œ 'A' ๋…ธ๋“œ์—์„œ ์‹œ์ž‘ํ•˜์—ฌ DFS๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉด, 'B', 'D', 'C'์ˆœ์„œ๋กœ ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

728x90