Kruskal algorithm - MST

2021-08-08 21:23:10

#Computer Science#Algorithm

kruskal 알고리즘은 최소 신장 트리 (Minimum Spanning Tree,MST)를 구하는 알고리즘으로, 그리디 알고리즘에 속한다

kruskal 알고리즘에 대해 배우기 전에 기본적으로 그래프에서 신장트리,연결성분등 용어를 알아야 원할하게 이해할 수 있다.

  • 연결성분(Connected Component): 그래프에서 정점들이 서로 연결되어 있는 부분

  • 신장트리(Spanning Tree) : 주어진 그래프가 하나의 연결 성분으로 구성되어 있을떄, 그래프의 모든 정점들을 cycle없이 연결하는 부분그래프

  • 최소 신장 트리 (MST): 하나의 연결성분으로 이루어진 무방향 가중치 그래프 에서 간선의 가중치의 합이 최소인 신장트리 , 당연히 신장트리 임으로 cycle이 있어서는 안된다.

kruskal 알고리즘의 수행과정은 다음과 같다.

  1. 가중치가 감소하지 않는 순서로 정렬한다.
  2. 가중치가 가장 작은 간선이 cycle을 만들지 않으면 신장트리 간선으로 선택한다.
  3. 2번 과정을 N(정점의 개수)-1 개수의 간선이 선택될떄까지 반복한다.

kruskal-algorithm

위 수행과정에서 가중치가 작은 순서대로 신장트리 간선을 선택하는데, cycle을 형성하는 4번은 제외되었다.

kruskal algorithm을 python으로 구현하면 다음과 같다.

from collections import deque;
weights = [(0,1,9),(0,2,10),(1,3,10),(1,4,5),
           (1,6,3),(2,3,9),(2,4,7),(2,5,2),
           (3,5,4),(3,6,8),(4,6,1),(5,6,6)
        ] ##(간선A,간선B,가중치)
#오름차순으로 가중치 정렬
weights.sort(key = lambda t :  t[2]);
weights = deque(weights);
mst= []; N = 7;
# disjoint set (서로소 집합)
p = [ i for i in range(N)];

# 서로소를 구하기 위한 find,union 연산 
# find : 노드의 집합의 루트 노드(=대표노드)를 찾는 연산 
def find(u):
    if u != p[u]:
        # 경로 압축 (find연산을 수행하면서 루트까지 올라가는 경로 상의 각 노드의 부모노드를 루트노드로 갱신한다. )
        p[u] = find(p[u]);
    return p[u];

# union : 두 노드를 하나의 집합으로 합친다
def union(u,v):
    root1 = find(u);
    root2 = find(v);
    p[root2] = root1;
    
tree_edges=0;
mst_cost=0;

while tree_edges!=(N-1):
    #가중치가 가장 작은 간선을 선택하고,
    u,v,wt = weights.popleft();
    # 해당 노드의 루트노드를 비교해 다르면 , 서로 다른 집합임을 확인 (cycle이 형성되지 않음을 확인 )
    if find(u) != find(v):
        # 두 노드를 하나의 집합으로 합침 
        union(u,v);
        # 최소 신장트리의 간선으로 선택 
        mst.append((u,v));
        mst_cost+=wt;
        tree_edges+=1;
print(mst);
    

시간복잡도

kruskal 알고리즘의 수행시간은 find-union algorithm의 시간복잡도와 거의 동일하다 (O(MlogN))

Reference

프로필 이미지
@chani
바둑 좋아하는 개발자의 의미있는 학습 기록을 위한 공간입니다.

댓글

이 게시글에 대한 의견을 공유해주세요!

댓글