Data structures (with python) - 2. Graph - 2.3. Spanning Tree

2024. 1. 3. 20:10ใ†CS - Roadmap.sh/1. Data structures

Data structures (with python) - 2. Graph - 2.3. Spanning Tree

 

Spanning Tree

 

๐Ÿ’ก A spanning tree is a subset of Graph G, which has all the vertices covered with minimum possible number of edges. Hence, a spanning tree does not have cycles and it cannot be disconnected..

์ŠคํŒจ๋‹ ํŠธ๋ฆฌ๋Š” ๊ทธ๋ž˜ํ”„ G์˜ ํ•˜์œ„ ์ง‘ํ•ฉ์œผ๋กœ, ๋ชจ๋“  ์ •์ ์ด ๊ฐ€๋Šฅํ•œ ์ตœ์†Œ ์ˆ˜์˜ ์—์ง€๋กœ ๋ฎ์—ฌ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ์—๋Š” ์ฃผ๊ธฐ๊ฐ€ ์—†์œผ๋ฉฐ ์—ฐ๊ฒฐ์ด ๋Š์–ด์งˆ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

 

 

https://www.tutorialspoint.com/data_structures_algorithms/spanning_tree.htm

 

 

Spanning Tree ๋Š”  ๋’ค์— Tree ๋ผ๊ณ  ๋ถ™์ง€๋งŒ ๊ตฌ์ง€ ๋ถ„๋ฅ˜ํ•˜์ž๋ฉด Tree๋ณด๋‹ค graph theory์˜ ์ค‘์š” ๊ฐœ๋…์— ์†ํ•œ๋‹ค.
์•ž์„œ ๊ทธ๋ž˜ํ”„ ์ด๋ก ์€, ๋…ธ๋“œ(node)์™€ ๊ทธ์‚ฌ์ด๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ์—ฃ์ง€(edge)์˜ ์ง‘ํ•ฉ์œผ๋กœ ์ด๋ฃจ์–ด์ง„ ๊ทธ๋ž˜ํ”„๋ฅผ ์—ฐ๊ตฌํ•œ๋‹ค.

 

์ŠคํŒจ๋‹ ํŠธ๋ฆฌ๋Š” ๊ทธ๋ž˜ํ”„์˜ ์„œ๋ธŒ๊ทธ๋ž˜ํ”„(subgraph)์ด๋ฉฐ,

๊ทธ๋ž˜ํ”„์˜ ํŠธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋‚˜ํƒ€๋‚ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋ž˜ํ”„ ์ด๋ก ์˜ ์ผ๋ถ€๋กœ ๋ถ„๋ฅ˜๋œ๋‹ค.

 

(Tree ์ด๋ก ์—๋Š” - binary, binary search, full binary, complete binary, balanced, unbalanced Tree ๋“ค์ด ์žˆ๋‹ค.
์ด ์‹œ๋ฆฌ์ฆˆ์—์„œ ์ •๋ฆฌํ•  tree๋“ค ์ด๋‹ค.)

 

 

 

์ตœ์†Œ ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์—๋Š”

kruskal๊ณผ prim ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์žˆ๋‹ค.

 

Kruskal ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ํŒŒ์ด์ฌ์—์„œ ๊ตฌํ˜„ํ•ด๋ณด์ž

class Graph:
    def __init__(self, vertices):
        self.V = vertices
        self.graph = []
	# ๊ทธ๋ž˜ํ”„๋ฅผ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.
    # vertices๋Š” ๊ทธ๋ž˜ํ”„์˜ ์ •์ ์˜ ์ˆ˜
    # self.graph ๊ทธ๋ž˜ํ”„์˜ ๊ฐ„์„ ์„ ์ €์žฅํ•˜๋Š” ๋ฆฌ์ŠคํŠธ

    def add_edge(self, u, v, w):
        self.graph.append([u, v, w])
	# u, v ๋Š” ๊ฐ„์„ ์˜ ์–‘ ๋ ์ •์ 
    # w๋Š” ๊ฐ„์„ ์˜ ๊ฐ€์ค‘์น˜

    def find(self, parent, i):
        if parent[i] == i:
            return i
        return self.find(parent, parent[i])
	#fine(self, parent, i)์ด ๋ฉ”์„œ๋“œ์—์„œ ๋ถ€๋ชจ๋ฐฐ์—ด์˜ i ๋ฒˆ์งธ ์ •์ ์˜ ๋ฃจํˆฌ๋ฅผ ์ฐพ๋Š”๋‹ค.


    def union(self, parent, rank, x, y):
        xroot = self.find(parent, x)
        yroot = self.find(parent, y)
        if rank[xroot] < rank[yroot]:
            parent[xroot] = yroot
        elif rank[xroot] > rank[yroot]:
            parent[yroot] = xroot
        else :
            parent[yroot] = xroot
            rank[xroot] += 1
	# union ๋ฉ”์„œ๋“œ๋Š” ๋‘ ๊ฐœ์˜ ์„œ๋กœ ๋‹ค๋ฅธ ์ง‘ํ•ฉ์„ ํ•ฉ์นœ๋‹ค.
    # x, y๋Š” ๊ฐ๊ฐ ์ง‘ํ•ฉ์„ ๋Œ€ํ‘œํ•˜๋Š” ๋ฃจํŠธ ์ •์ 
    # ์ด ๋ฉ”์„œ๋“œ์—์„œ ๋‘ ์ง‘ํ•ฉ์˜ rank๋ฅผ ๋น„๊ตํ•ด ๋žญํฌ๊ฐ€ ๋” ๋‚ฎ์€ ์ง‘ํ•ฉ์„ ๋žญํฌ๊ฐ€ ๋” ๋†’์€ ์ง‘ํ•ฉ์— ํ•ฉ์นœ๋‹ค.
    # ๋žญํฌ๊ฐ€ ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” ํ•œ ์ง‘ํ•ฉ์„ ๋‹ค๋ฅธ ์ง‘ํ•ฉ์— ํ•ฉ์น˜๊ณ  ๋žญํฌ๋ฅผ 1 ์ฆ๊ฐ€์‹œํ‚จ๋‹ค.


    def kruskal(self):
        result = []
        i = 0
        e = 0
        self.graph = sorted(self.graph, key=lambda item: item[2])
        parent = []
        rank = []
        for node in range(self.V):
            parent.append(node)
            rank.append(0)
        while e < self.V - 1:
            u, v, w = self.graph[i]
            i += 1
            x = self.find(parent, u)
            y = self.find(parent, v)
            if x != y:
                e += 1
                result.append([u, v, w])
                self.union(parent, rank, x, y)
        return result
        
	# kruskal ์ด ๋ฉ”์„œ๋“œ๋Š” ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‹คํ–‰, ์ตœ์†Œ ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ๋ฅผ ์ฐพ๋Š”๋‹ค.
    # ๊ฐ„์„ ๋“ค์„ ๊ฐ€์ค‘์น˜์˜ ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ•˜๊ณ (sorted),
    # ๊ฐ€์žฅ ๊ฐ€์ค‘์น˜๊ฐ€ ์ž‘์€ ๊ฐ„์„ ๋ถ€ํ„ฐ ์„ ํƒํ•˜์—ฌ ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ์— ์ถ”๊ฐ€ํ•œ๋‹ค.
    # ๊ฐ„์„ ์„ ์ถ”๊ฐ€ํ•  ๋•Œ์— ํ•ด๋‹น ๊ฐ„์„ ์ด ์‚ฌ์ดํด์„ ํ˜•์„ฑํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ณ ,
    # ์‚ฌ์ดํด์„ ํ˜•์„ฑํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์—๋งŒ ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ์— ์ถ”๊ฐ€ํ•œ๋‹ค

 

์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ํด๋ž˜์Šค์˜ ๊ฐ ๋ฉ”์„œ๋“œ ๋งˆ๋‹ค ์ฃผ์„์„ ๋‹ฌ์•„๋†“์•˜๋‹ค.

 

g = Graph(4)
g.add_edge(0, 1, 10)
g.add_edge(0, 2, 6)
g.add_edge(0, 3, 5)
g.add_edge(1, 3, 15)
g.add_edge(2, 3, 4)

print(g.kruskal())  # [[2, 3, 4], [0, 3, 5], [0, 1, 10]]

์œ„ ์ฝ”๋“œ๋Š” 4๊ฐœ์˜ ๋…ธ๋“œ์™€ 5๊ฐœ์˜ ๊ฐ„์„ ์„ ๊ฐ€์ง„ ๊ทธ๋ž˜ํ”„์—์„œ ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ๋ฅผ ์ฐพ๋Š”๋‹ค.

๊ฒฐ๊ณผ๋Š” ์„ ํƒ๋œ ๊ฐ„์„ ๋“ค๊ณผ ๊ฐ ๊ฐ„์„ ์˜ ๊ฐ€์ค‘์น˜๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.

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

 

 

4๊ฐœ์˜ ๋…ธ๋“œ (0123), 5 ๊ฐœ์˜ ๊ฐ„์„  (0-1, 0-2, 0-3, 1-3, 2-3) ์œผ๋กœ ์ƒ์„ฑํ•œ๋‹ค.

๊ฐ ๊ฐ€์ค‘์น˜ (10,6,5,15,4)

 

ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๊ฐ€์žฅ ๊ฐ€์ค‘์น˜๊ฐ€ ์ž‘์€ ๊ฐ„์„ ๋ถ€ํ„ฐ ์„ ํƒํ•œ๋‹ค.

1. ๊ฐ€์ค‘์น˜4 ์ธ ๊ฐ„์„  2-3 ์„ ํƒ. -> [[2,3,4]]

 

2. ์ฐจ๋ก€๋Œ€๋กœ ๊ฐ€์ค‘์น˜ 5์ธ 0-3

[[2,3,4], [0,3,5]]


3. ๊ทธ๋‹ค์Œ ๊ฐ€์ค‘์น˜ 6์ธ ๊ฐ„์„  0-2๋ฅผ ์„ ํƒํ•˜๊ณ  ์ถ”๊ฐ€ํ•˜๋ฉด
์‚ฌ์ดํด 0-2-3-0 ์ด ํ˜•์„ฑ๋˜์–ด ๋ฒ„๋ ค ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ๊ฐ€ ์•„๋‹ˆ๋‹ค.

4.  ๊ทธ๋‹ค์Œ ๊ฐ€์ค‘์น˜ 10 , 0-1์„ ์„ ํƒํ•˜๋ฉด ์‚ฌ์ดํด์ด ํ˜•์„ฑ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ์— ์ถ”๊ฐ€ํ•œ๋‹ค.

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

5. ๋งˆ์ง€๋ง‰ ๊ฐ€์ค‘์น˜ 15, 1-3 ์€ 
์ด๋ฏธ 0-1, 0-3 ๊ฐ„์„ ์ด ์„ ํƒ๋˜์–ด์žˆ๋‹ค. 

๋”ฐ๋ผ์„œ 1-3 ๊ฐ„์„ ์„ ์ถ”๊ฐ€ํ•˜๋ฉด 1-0-3-1 ์ด๋Ÿฐ ์‚ฌ์ดํด์ด ํ˜•์„ฑ ๋œ๋‹ค.

๋”ฐ๋ผ์„œ ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ์— ์ถ”๊ฐ€๋˜์ง€ ์•Š๋Š”๋‹ค.

 

 

์ตœ์ข…์ ์ธ ์ตœ์†Œ ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ๋Š” 2-3, 0-3, 0-1๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋Š”

[[2,3,4],[0,3,5],[0,1,10]]์ด ๋œ๋‹ค.

 

์ •๋ฆฌ

์ŠคํŒจ๋‹ ํŠธ๋ฆฌ (Spanning tree)๋Š”

1. cycle(loop)๊ฐ€ ์—†๋‹ค.

2. ๋ชจ๋“  ์ •์ ์ด ๊ฐ€๋Šฅํ•œ ์ตœ์†Œ ์ˆ˜์˜ ์—์ง€๋กœ ๋ฎ์—ฌ์žˆ๋‹ค.

 

ํ™œ์šฉ

1. ๋„คํŠธ์›Œํฌ ๊ณ„ํš

2. ์ปดํ“จํ„ฐ ๋„คํŠธ์›Œํฌ ๋ผ์šฐํŒ… ํ”„๋กœํ† ์ฝœ

3. ํด๋Ÿฌ์Šคํ„ฐ ๋ถ„์„

728x90