在VisualStudio2017中,新建控制台应用程序DemoMst。新建类 MinSpanningTree.cs。输入以下测试代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DemoMst
{
/// <summary>
/// 【图论】最小生成树
/// </summary>
public class MinSpanningTree
{
/// <summary>
/// 无穷远的距离(权重),两点之间不能直接到达就认为是无穷的
/// </summary>
public const int Infinity = 99999;
/// <summary>
/// 顶点个数
/// </summary>
public const int VertexCount = 6;
/// <summary>
/// 顶点集合
/// </summary>
public string[] VertexCollection = new string[VertexCount];
/// <summary>
/// 点与点之间的距离(权重),两点不是直接相连,则默认距离是无穷(Infinity)的
/// </summary>
public int[,] Matrix = new int[VertexCount, VertexCount];
/// <summary>
/// 设置一个顶点
/// </summary>
/// <param name="index"></param>
/// <param name="label"></param>
public void SetVertex(int index, string label)
{
if (index < 0 || index >= VertexCount)
{
throw new Exception("顶点数组VertexCollection索引越界");
}
VertexCollection[index] = label;
}
/// <summary>
/// 添加一条边【默认边为双向的】
/// </summary>
/// <param name="start"></param>
/// <param name="end"></param>
/// <param name="distance"></param>
public void AddEdge(int start, int end, int distance)
{
Matrix[start, end] = distance;
//如果边Edge时双向的,则增加下面一行代码
Matrix[end, start] = distance;
}
/// <summary>
/// 初始化
/// </summary>
public void Init()
{
//初始化顶点
SetVertex(0, "A");
SetVertex(1, "B");
SetVertex(2, "C");
SetVertex(3, "D");
SetVertex(4, "E");
SetVertex(5, "F");
//初始化认为都无法直接到达,即:距离是无穷的
for (int i = 0; i < VertexCount; i++)
{
for (int j = 0; j < VertexCount; j++)
{
Matrix[i, j] = Infinity;
}
}
//初始化可以直接到达的边
//AB=3,AD=2,AF=7,
//BC=4,BD=5,BE=6,
//CE=4,CF=6,
//DE=4,DF=4,
//EF=3
AddEdge(0, 1, 3);
AddEdge(0, 3, 2);
AddEdge(0, 5, 7);
AddEdge(1, 2, 4);
AddEdge(1, 3, 5);
AddEdge(1, 4, 6);
AddEdge(2, 4, 4);
AddEdge(2, 5, 6);
AddEdge(3, 4, 4);
AddEdge(3, 5, 4);
AddEdge(4, 5, 3);
}
/// <summary>
/// 获取最小生成树
/// </summary>
public void GetMinSpanTree()
{
//初始定义一个集合,集合元素为空
List<int> list = new List<int>();
//第一个点A,其他点BCDEF
int startIndex = 0;
list.Add(startIndex);
Console.WriteLine(string.Join(",", list));
int nextIndex = GetNextMinVertex(list);
//如果存在下一个节点,并且集合中不存在该元素
if (nextIndex != -1 && !list.Contains(nextIndex))
{
list.Add(nextIndex);
Console.WriteLine(string.Join(",", list));
}
while (list.Count < VertexCount)
{
nextIndex = GetNextMinVertex(list);
if (nextIndex == -1)
{
break;
}
if (nextIndex != -1 && !list.Contains(nextIndex))
{
list.Add(nextIndex);
Console.WriteLine(string.Join(",", list));
}
}
}
/// <summary>
/// 找出当前已选择起点集合可到达的顶点的当前最短距离的 索引,没有找到符合的则返回-1
/// </summary>
/// <param name="list">已找到的最短距离的顶点集合</param>
/// <returns></returns>
public int GetNextMinVertex(List<int> list)
{
int minIndex = -1;//到达顶点索引
int minValue = Infinity;//两点间的距离
int fromIndex = -1;//起始顶点索引
for (int index = 0; index < list.Count; index++)
{
//以每一个已找到的最短距离的最小顶点作为起始顶点,穷举遍历出剩下的最短距离的下一个顶点
int startIndex = list[index];
for (int i = 0; i < VertexCount; i++)
{
//贪婪法则,找出不存在集合中,最小的值的索引
if (!list.Contains(i) && Matrix[startIndex, i] < minValue)
{
minIndex = i;
minValue = Matrix[startIndex, i];
fromIndex = startIndex;
}
}
}
Console.WriteLine("从【{0}】到【{1}】,当前距离:{0}{1}={2}", VertexCollection[fromIndex], VertexCollection[minIndex], minValue);
return minIndex;
}
}
}
在默认的Program.cs中的Main函数中,测试代码如下:
MinSpanningTree mst = new MinSpanningTree();
mst.Init();
mst.GetMinSpanTree();
Console.ReadLine();
运行后结果截图: