Data structures (with python) - 2. Graph - 2.2. Undirected graph

2024. 1. 2. 21:43ใ†CS - Roadmap.sh/1. Data structures

Data structures (with python) - 2. Graph - 2.2. Undirected graph

 

๐Ÿ’ก An undirected graph is graph, i.e., a set of objects (called vertices or nodes) that are connected together, where all the edges are bidirectional. An undirected graph is sometimes called an undirected network. In contrast, a graph where the edges point in a direction is called a directed graph.

 

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

 

 

ํŒŒ์ด์ฌ์—์„œ ์—ญ์‹œ undirected graph ๋ฅผ ์„ค๋ช…ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ 
์•ž์„  directed graph์—์„œ ์„ค๋ช…ํ• ๋•Œ ์‚ฌ์šฉํ–ˆ๋˜ ์ธ์ ‘๋ฆฌ์ŠคํŠธ(Adjacency List)์™€ ์ธ์ ‘ ํ–‰๋ ฌ(Adjacency Matrix)๋ฅผ ์ด์šฉํ•œ๋‹ค.

 

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

- ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ๋Š” ๊ทธ๋ž˜ํ”„์˜ ๊ฐ ๋…ธ๋“œ์— ๋Œ€ํ•œ ์ธ์ ‘ ๋…ธ๋“œ์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐฉ์‹.

- ํŒŒ์ด์ฌ์—์„œ๋Š” ๋”•์…”๋„ˆ๋ฆฌ์™€ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ด์šฉํ•ด์„œ ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ๋ฅผ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D', 'E'],
    'C': ['A', 'F'],
    'D': ['B'],
    'E': ['B', 'F'],
    'F': ['C', 'E'],
}

 

์ด graph๋Š” 'A':['B','C']๋Š” A ๋…ธ๋“œ๊ฐ€ B์™€ C ๋…ธ๋“œ์™€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋”ฐ๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

 

2. ์ธ์ ‘ํ–‰๋ ฌ (Adjacency Matrix)

- ์ธ์ ‘ ํ–‰๋ ฌ์€ ๊ทธ๋ž˜ํ”„์˜ ๊ฐ ๋…ธ๋“œ๊ฐ€ ๋‹ค๋ฅธ ๋…ธ๋“œ์™€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š”์ง€๋ฅผ ์ด์ง„๊ฐ’(0 ๋˜๋Š” 1)์œผ๋กœ ํ‘œํ˜„ํ•œ 2์ฐจ์› ํ–‰๋ ฌ

- ํŒŒ์ด์ฌ์—์„œ๋Š” 2์ฐจ์› ๋ฆฌ์ŠคํŠธ๋ฅผ ์ด์šฉํ•ด ์ธ์ ‘ ํ–‰๋ ฌ์„ ํ‘œํ˜„ํ• ์ˆ˜ ์žˆ๋‹ค.

graph = [
    [0, 1, 1, 0, 0, 0],
    [1, 0, 0, 1, 1, 0],
    [1, 0, 0, 0, 0, 1],
    [0, 1, 0, 0, 0, 0],
    [0, 1, 0, 0, 0, 1],
    [0, 0, 1, 0, 1, 0]
]

 

์ด ์ธ์ ‘ํ–‰๋ ฌ์€ 6๊ฐœ์˜ ๋…ธ๋“œ๊ฐ€ ์žˆ๋Š” ๋ฌด๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„์ด๋‹ค.

๋…ธ๋“œ 0 - 1,2 ์—ฐ๊ฒฐ

1 - 0,3,4 ์—ฐ๊ฒฐ

2 - 0,5 ์—ฐ๊ฒฐ

3 - 1 ์—ฐ๊ฒฐ

4 - 1,5 ์—ฐ๊ฒฐ

5 - 2,4 ์—ฐ๊ฒฐ

 

(์ฐจํ›„ ๊ทธ๋ฆผ ์ถ”๊ฐ€)

 

 

 

class UndirectedGraph:
    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)
        
        if neighbour not in self.graph:
            self.graph[neighbour] = [node]
        else:
            self.graph[neighbour].append(node)


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

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

 

์•ž์„œ Directed graph์—์„œ๋Š” DFS๋กœ ๊ทธ๋ž˜ํ”„๋ฅผ ํƒ์‚ฌํ–ˆ๊ธฐ์—, ์ด๋ฒˆ์—๋Š” BFS๋กœ ํƒ์‚ฌํ•ด๋ณธ๋‹ค.

์ด ๊ทธ๋ž˜ํ”„๋ฅผ BFSํ•˜๋Š” ๋ฉ”์„œ๋“œ๋กœ ๋…ธ๋“œ๋ฅผ ์ฐจ๋ก€๋Œ€๋กœ ํƒ์ƒ‰ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

    def bfs(self, node): # ๋“ค์—ฌ์“ฐ๊ธฐ ์ฃผ์˜
        visited = []
        queue = [node]

        while queue:
            current_node = queue.pop(0)
            if current_node not in visited:
                visited.append(current_node)
                if current_node in self.graph:
                    queue.extend(self.graph[current_node])
        return visited

 

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

 

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

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

 

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

728x90