자료구조

[파이썬 자료구조] Partition or Disjoint Set

j9m 2020. 6. 20. 19:27
반응형

이전 포스팅에서 Kruskal 알고리즘에 대해서 알아보았음.

 

[파이썬 자료구조] Kruskal 알고리즘

[파이썬 자료구조] 그래프(Graph) 그래프(G)는 정점(V)과 간선(E)으로 이루어져 있음 그래프의 종류 -무방향 그래프: 간선에 방향성이 없음 -방향성 그래프: 간선에 방향성이 있음 -가중치그래프: 간�

ohaengsa.tistory.com


Kruskal 알고리즘에서 cycle 여부를 확인하는 과정임.

정점X와 정점Y를 직접 연결하려할 때 정점X에서 Y로 가는 경로가 이미 존재하는지 확인하는 방법

만약 X,Y가 Z를 통해 연결되어있다면 X,Y를 직접 연결하는 edge를 버림

자기 자신을 가르키는 하나의 원소로 이루어짐 5개의 집합있다고 가정함.

{0}과 {1}을 합치면 1은 0을 가르킨다.

 

왼쪽 그림에서 fInd(1)을 했을 때, 1->2->7->10의 경로를 알고 루트를 알 수 있음

이 과정을 압축해서 1->10로 함 (오른쪽 그림처럼) 

find(1)을 통해서 다른 원소들에 대한 수행시간이 줄게됨

파이썬으로 Kruskal과 Partition을 구현하면해서 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Partition:
    class Node:
        def __init__(self, container, e):
            self._container = container
            self._element = e
            self._size = 1
            self._parent = self
        
        def element(self):
            return self._element
        
        def make_group(self, e): #각각 한 개의 원소로 이루어져있는 집합
            return self.Node(self, e)
        
        def find(self, p):
            if p._parent != p:
                p._parent = self.find(p._parent) 
                return p._parent
        
        def union(self, p, q):
            a = self.find(p)
            b = self.find(q)
            if a is not b: 
                if a._size > b._size:
                    b._parent = a
                    a._size += b._size
                else:
                    a._parent = b
                    b._size += a._size
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import Partition
 
def MST_Kruskal(g):
    tree = [] # list of edges in spanning tree
    pq = HeapPriorityQueue() #heap을 구현해서 사용
    forest = Partition() # keeps track of forest clusters
    position = {} # map each node to its Partition entry
    for v in g.vertices():
        position[v] = forest.make_group(v) #각각의 원소들을 하나의 집합으로 만듬
    for e in g.edges():
        pq.add(e.element(), e) # edge's element is assumed to be its weight
    size = g.vertex_count()
    while len(tree) != size - 1 and not pq.is_empty():
        weight, edge = pq.remove_min()
        u, v = edge.endpoints()
        a = forest.find(position[u])
        b = forest.find(position[v])
        if a != b: #cycle이 없다면
            tree.append(edge)
            forest.union(a, b)
    return tree
 

 



먼저 HeapPriorityqueue를 구현. heap은 통해 쉽게 구현 가능할 거임

edge의 개수 m의 최대값은 n(n-1)/2

정점에 대해 find를 하였을때 경로 압축이 일어나므로 복잡함

 

 

 

 

반응형