C#图的最短路径算法示例

在visual studio 新建控制台项目TestGraph。该图认为是无向的。求出起点A到达其他任意顶点之间的最短距离以及路径。

节点之间的权重认为都是正数。

程序测试代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestGraph
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("图(Graph)是由顶点(Vertex)和边(Edge)组成,下面程序演示最短路径...");
            Graph graph = new Graph();
            graph.Init();
            graph.Path();
            graph.Print();
            Console.ReadLine();
        }
    }

    class Graph 
    {
        /// <summary>
        /// 顶点个数
        /// </summary>
        public const int VertexCount = 6;
        /// <summary>
        /// 无法直接到达的距离,无限远的距离
        /// </summary>
        public const int Infinity = 99999;
        /// <summary>
        /// 顶点组成的数组
        /// </summary>
        public Vertex[] VertexArr = new Vertex[VertexCount];
        /// <summary>
        /// 起始顶点到每个顶点之间的最短距离组成的数组
        /// </summary>
        public MinDistance[] MinDistanceArr = new MinDistance[VertexCount];
        /// <summary>
        /// 顶点到顶点之间组成的矩阵数组
        /// </summary>
        public int[,] Matrix = new int[VertexCount, VertexCount];
        /// <summary>
        /// 当前索引
        /// </summary>
        public int CurrentIndex = 0;

        /// <summary>
        /// 添加一个顶点
        /// </summary>
        /// <param name="label"></param>
        public void AddVertex(string label) 
        {
            if (CurrentIndex >= VertexCount) 
            {
                throw new Exception("添加顶点已超过限度个数:" + VertexCount);
            }
            VertexArr[CurrentIndex] = new Vertex(label);
            CurrentIndex++;
        }

        /// <summary>
        /// 添加一条边【认为距离是无向的 即A→B,同时B→A】
        /// </summary>
        /// <param name="startIndex"></param>
        /// <param name="endIndex"></param>
        /// <param name="distance"></param>
        public void AddEdge(int startIndex, int endIndex, int distance) 
        {
            Matrix[startIndex, endIndex] = distance;
            //如果距离是有方向的,则去掉下面一行
            Matrix[endIndex, startIndex] = distance;
        }

        /// <summary>
        /// 初始化
        /// </summary>
        public void Init() 
        {
            AddVertex("A");//0
            AddVertex("B");//1
            AddVertex("C");//2
            AddVertex("D");//3
            AddVertex("E");//4
            AddVertex("F");//5

            //初始化最短距离为无穷大,所有矩阵距离都为无穷大
            for (int i = 0; i < VertexCount; i++)
            {
                MinDistanceArr[i] = new MinDistance { ParentIndex = 0, Distance = Infinity };
                for (int j = 0; j < VertexCount; j++)
                {
                    Matrix[i, j] = Infinity;
                }
            }

            //AB AC AD
            AddEdge(0, 1, 5);
            AddEdge(0, 2, 3);
            AddEdge(0, 3, 19);
            //BC BE
            AddEdge(1, 2, 10);
            AddEdge(1, 4, 8);
            //CD CE CF
            AddEdge(2, 3, 14);
            AddEdge(2, 4, 12);
            AddEdge(2, 5, 9);
            //DE DF
            AddEdge(3, 4, 5);
            AddEdge(3, 5, 4);
            //EF
            AddEdge(4, 5, 4);
        }

        /// <summary>
        /// 找出最短路径
        /// </summary>
        public void Path()
        {
            //假设定义起点为A
            int startIndex = 0;
            VertexArr[startIndex].IsVisited = true;
            for (int i = 0; i < VertexCount; i++)
            {
                if (Matrix[startIndex, i] < MinDistanceArr[i].Distance)
                {
                    MinDistanceArr[i].Distance = Matrix[startIndex, i];
                }
            }

            for (int cnt = 1; cnt < VertexCount; cnt++)
            {
                //找出未访问的顶点中,距离最小的顶点的起点索引
                int minIndex = -1;//最小距离所在的索引
                int minDist = Infinity;//最小距离
                for (int i = 0; i < VertexCount; i++)
                {
                    if (!VertexArr[i].IsVisited && MinDistanceArr[i].Distance < minDist)
                    {
                        minIndex = i;
                        minDist = MinDistanceArr[i].Distance;
                    }
                }
                //则最短路径被范围,并且找出更短的距离
                VertexArr[minIndex].IsVisited = true;
                for (int i = 0; i < VertexCount; i++)
                {
                    //如果当前节点未访问,并且 最短距离+【最短距离的顶点可到达的顶点的距离之和】
                    if (!VertexArr[i].IsVisited && minDist + Matrix[minIndex, i] < MinDistanceArr[i].Distance)
                    {
                        MinDistanceArr[i].Distance = minDist + Matrix[minIndex, i];
                        MinDistanceArr[i].ParentIndex = minIndex;
                    }
                }
            }
        }

        /// <summary>
        /// 打印消息
        /// </summary>
        public void Print() 
        {
            for (int i = 0; i < VertexCount; i++)
            {
                Console.WriteLine("最短路径长度:A->{0}:{1},上一父节点:{2}.完全路线:{3}",
                    VertexArr[i].Label, MinDistanceArr[i].Distance, MinDistanceArr[i].ParentIndex, GetSerialPath(i));
                
            }
        }

        /// <summary>
        /// 获取连续节点路线
        /// </summary>
        /// <param name="parentIndex"></param>
        /// <returns></returns>
        public string GetSerialPath(int parentIndex) 
        {
            Stack<string> stack = new Stack<string>();
            stack.Push(VertexArr[parentIndex].Label);
            while (parentIndex != 0)
            {
                parentIndex = MinDistanceArr[parentIndex].ParentIndex;
                stack.Push(VertexArr[parentIndex].Label);
            }
            return string.Join("->", stack);
        }
    }

    /// <summary>
    /// 顶点
    /// </summary>
    class Vertex 
    {
        /// <summary>
        /// 是否已访问该顶点
        /// </summary>
        public bool IsVisited { get; set; }
        /// <summary>
        /// 顶点名称
        /// </summary>
        public string Label { get; set; }

        public Vertex(string label) 
        {
            this.IsVisited = false;
            this.Label = label;
        }
    }

    /// <summary>
    /// 最短距离:两个顶点之间的最短距离
    /// </summary>
    class MinDistance 
    {
        /// <summary>
        /// 上一节点索引
        /// </summary>
        public int ParentIndex { get; set; }
        /// <summary>
        /// 最短距离
        /// </summary>
        public int Distance { get; set; }
    }
}
 

程序运行效果如图:

©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值