核心思想
假设连通网G=(V,E),令最小生成树的初始状态为只有n个顶点而无边的非连通图T=(V,{}),概述图中每个顶点自成一个连通分量。在E中选择代价最小的边,若该边依附的顶点分别在T中不同的连通分量上,则将此边加入到T中;否则,舍去此边而选择下一条代价最小的边。依此类推,直至T中所有顶点构成一个连通分量为止
理解:图中的每个顶点都是一个连通分量,每次去寻找权值最小的边,然后判断最小生成树加入这条边是否会形成环,意思就是如果在不同的连通分量中则可以加入,如果在想通的连通分量中则不可以合并因为会构成环,怎么去判断是否在同一个连通分量中,就是判断他们是否在一个集合中。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Kruskal
{
public class Vertex
{
public object Data;
public Vertex(object data)
{
this.Data = data;
}
}
public class Edge
{
public int Start;
public int End;
public int Weight;
public Edge(int start, int end, int weight)
{
this.Start = start;
this.End = end;
this.Weight = weight;
}
}
public class Graph
{
public int VertexCount;
public Edge[] Edges;
public Vertex[] Vertexs;
public Graph(Vertex[] vertexs,Edge[] edges)
{
this.Vertexs = vertexs;
this.Edges = edges;
this.VertexCount = vertexs.Length;
}
private static void SortEdges(Edge[] edges)
{
for (int i = 0; i < edges.Length-1; i++)
{
if (edges[i].Weight > edges[i+1].Weight)
{
Edge t = edges[i];
edges[i] = edges[i + 1];
edges[i + 1] = t;
}
}
}
private static int Find(int[] Vertexs,int index)
{
while (Vertexs[index] > -1)
{
index = Vertexs[index];
}
return index;
}
public static void Kruskal(Graph graph)
{
//1.生成父亲数组用于判断是否在想通的连通分量中
int[] parent = new int[graph.VertexCount];
for (int i = 0; i < parent.Length; i++)
{
parent[i] = -1;
}
//2.对边进行排序
SortEdges(graph.Edges);
//3.判断是否在想通的连通分量中=是否构成回路(环)
for (int i = 0; i < graph.Edges.Length; i++)
{
int startRoot = Find(parent, graph.Edges[i].Start);
int endRoot = Find(parent, graph.Edges[i].End);
if (startRoot != endRoot)
{
parent[endRoot] = startRoot;
Debug.LogError("(" + graph.Edges[i].Start + "," + graph.Edges[i].End + ") ");
}
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Kruskal;
public class TestKruskal : MonoBehaviour
{
Graph graph;
void Start()
{
Vertex[] vertexs = GenerateVertex(9);
Edge[] edges = GenerateEdges();
graph = new Graph(vertexs, edges);
Graph.Kruskal(graph);
}
private Vertex[] GenerateVertex(int len)
{
Vertex[] vertexs = new Vertex[len];
for (int i = 0; i < len; i++)
{
vertexs[i] = new Vertex(i);
}
return vertexs;
}
private Edge[] GenerateEdges()
{
Edge edge0 = new Edge(0, 1, 10);
Edge edge1 = new Edge(0, 5, 11);
Edge edge2 = new Edge(1, 2, 18);
Edge edge3 = new Edge(1, 6, 16);
Edge edge4 = new Edge(1, 8, 12);
Edge edge5 = new Edge(2, 3, 22);
Edge edge6 = new Edge(2, 8, 8);
Edge edge7 = new Edge(3, 4, 20);
Edge edge8 = new Edge(3, 7, 16);
Edge edge9 = new Edge(3, 8, 21);
Edge edge10 = new Edge(4, 5, 26);
Edge edge11 = new Edge(4, 7, 7);
Edge edge12 = new Edge(5, 6, 17);
Edge edge13 = new Edge(6, 7, 19);
Edge edge14 = new Edge(6, 7, 19);
Edge[] edges = { edge0, edge1, edge2, edge3, edge4, edge5, edge6, edge7, edge8, edge9, edge10, edge11, edge12, edge13, edge14 };
return edges;
}
}