Kruskal 알고리즘은 최소 신장 트리 문제를 해결하는 데 사용되는 그리디 알고리즘입니다. 최소 신장 트리는 연결된 무방향 그래프에서 간선 가중치의 합이 가장 작은 신장 트리입니다. Kruskal 알고리즘은 간선 가중치가 작은 것부터 큰 것 순으로 간선을 선택합니다. 선택한 간선이 순환을 형성하지 않으면 스패닝 트리에 추가됩니다. 구체적인 구현 프로세스는 다음과 같습니다.
가장자리 가중치에 따라 모든 가장자리를 작은 것부터 큰 것까지 정렬합니다.
선택한 모서리의 두 끝점이 동일한 연결된 구성 요소에 없으면 이 모서리를 최소 스패닝 트리에 추가하고 두 끝점을 동일한 연결된 구성 요소로 병합합니다.
최소 신장 트리가 그래프의 모든 정점을 포함할 때까지.
알고리즘의 장점은 모서리의 가중치에만 주의하면 되고 꼭지점의 정도와는 관련이 없으므로 조밀한 그래프에서도 더 좋은 성능을 나타낼 수 있다는 것입니다. 동시에 Kruskal의 알고리즘은 확장성이 뛰어나고 가중치 그래프에서 최소 신장 포리스트 문제를 쉽게 처리할 수 있습니다.
모든 가장자리를 작은 것부터 큰 것까지 정렬합니다.
이 가장자리로 연결된 두 노드가 동일한 연결된 구성 요소에 있지 않으면 가장자리를 추가합니다. 스패닝 트리로 이동하여 두 노드를 연결된 구성 요소로 병합합니다.
모든 노드가 동일한 연결된 구성 요소에 있고 이때 생성된 트리가 최소 스패닝 트리가 될 때까지 2단계를 반복합니다.
구현 과정에서 일반적으로 결합 조회를 사용하여 연결을 유지함으로써 효율성을 향상시킵니다.
import java.util.*; public class KruskalAlgorithm { // 定义边的数据结构 class Edge implements Comparable<Edge> { int src, dest, weight; public int compareTo(Edge edge) { return this.weight - edge.weight; } } // 并查集数据结构 class Subset { int parent, rank; } int V, E; // V是顶点数,E是边数 Edge edge[]; // 存储边的数组 // 构造函数,初始化边和顶点数 KruskalAlgorithm(int v, int e) { V = v; E = e; edge = new Edge[E]; for (int i = 0; i < e; ++i) edge[i] = new Edge(); } // 查找父节点 int find(Subset subsets[], int i) { if (subsets[i].parent != i) subsets[i].parent = find(subsets, subsets[i].parent); return subsets[i].parent; } // 合并两个子集 void union(Subset subsets[], int x, int y) { int xroot = find(subsets, x); int yroot = find(subsets, y); if (subsets[xroot].rank < subsets[yroot].rank) subsets[xroot].parent = yroot; else if (subsets[xroot].rank > subsets[yroot].rank) subsets[yroot].parent = xroot; else { subsets[yroot].parent = xroot; subsets[xroot].rank++; } } // 执行克鲁斯卡尔算法 void kruskal() { Edge result[] = new Edge[V]; // 存储结果的数组 int e = 0; // 表示result数组中的下标 // 将边按照权重从小到大排序 Arrays.sort(edge); // 创建V个子集 Subset subsets[] = new Subset[V]; for (int i = 0; i < V; ++i) subsets[i] = new Subset(); // 初始化每个子集的父节点和秩 for (int v = 0; v < V; ++v) { subsets[v].parent = v; subsets[v].rank = 0; } // 取E-1条边 int i = 0; while (e < V - 1) { Edge next_edge = new Edge(); next_edge = edge[i++]; int x = find(subsets, next_edge.src); int y = find(subsets, next_edge.dest); // 如果两个节点不在同一个集合中,合并它们 if (x != y) { result[e++] = next_edge; union(subsets, x, y); } } // 打印结果 System.out.println("Following are the edges in the constructed MST"); for (i = 0; i < e; ++i){ System.out.println(result[i].src + " - " + result[i" - " + result[i].weight); return; } // 定义一个辅助函数,用于查找结点所在的集合 private int find(int parent[], int i) { if (parent[i] == -1) return i; return find(parent, parent[i]); } // 定义一个辅助函数,用于合并两个集合 private void union(int parent[], int x, int y) { int xset = find(parent, x); int yset = find(parent, y); parent[xset] = yset; } } }
이 함수는 Arrays 클래스의 정렬 메서드를 사용하여 가중치에 따라 작은 것부터 큰 것까지 가장자리를 정렬합니다. 그런 다음 함수는 정렬된 가장자리를 순서대로 탐색하고 각 가장자리에 대해 find 함수를 사용하여 해당 집합의 src 및 dest가 있는 루트 노드를 찾습니다. 루트 노드가 다르다면 두 세트가 연결되어 있지 않아 병합이 가능하다는 뜻이며, 최소 신장 트리의 결과 배열에 에지가 추가된다는 뜻이다. 마지막으로 함수는 최소 신장 트리의 결과 배열을 순회하여 각 모서리의 시작점, 끝점 및 가중치를 출력합니다.
이 구현에서는 집합을 빠르게 검색하는 방법, 즉 통합 검색을 사용하여 이를 달성합니다. 각 노드에는 상위 배열이 있으며, 여기서 parent[i]는 노드 i의 상위 노드를 나타냅니다. parent[i] == -1인 경우 노드 i는 루트 노드입니다. 노드가 위치한 집합을 검색할 때, 현재 노드의 부모 노드가 -1이면 해당 노드가 루트 노드임을 의미하고, 그렇지 않으면 부모 노드가 있는 집합을 재귀적으로 검색한다. . 두 컬렉션을 병합할 때 병합할 두 컬렉션의 루트 노드를 찾아 한 루트 노드의 상위 노드를 다른 루트 노드의 인덱스로 설정합니다. 즉, 한 컬렉션의 루트 노드를 의 루트 노드 아래에 병합합니다. 다른 컬렉션.
이렇게 구현된 Kruskal 알고리즘의 시간 복잡도는 O(ElogE)입니다. 여기서 E는 그래프의 가장자리 수를 나타냅니다. 주요 시간 비용은 가장자리를 정렬하는 과정에 있습니다. 공간 복잡도는 O(V+E)입니다. 여기서 V는 그래프의 정점 수를 나타냅니다. 주요 공간 오버헤드는 가장자리와 상위 배열을 저장하는 것입니다.
위 내용은 Kruskal 알고리즘을 구현하는 Java 코드의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!