带权重的有向图求最短路径

首先新建一个网图如下:

带权重的有向图求最短路径

图的表示法有好多中,最常用的应该是邻接矩阵与邻接表。上面的图,边很少,用邻接表来表示就很不错。

对于以上图,可以对象出3个类。图、节点、边。3个实体类代码如下:

边Edge:

public class Edge
    {
        public string StartNodeID
        {
            get;
            set;
        }
        public string EndNodeID
        {
            get;
            set;
        }
        public int Weight
        {
            get;
            set;
        }
    }

节点Node:

public class Node
    {
        private string id;
        private IList edgeList;
        public Node(string nid)
        {
            id = nid;
            edgeList = new List();
        }

        public string Id
        {
            get
            {
                return id;
            }
        }

        public IList EdgeList
        {
            get
            {
                return edgeList;
            }
        }
    }

图Graph:

public class Graph
    {
        public List NodeList = new List();
    }

由于要求的就是最短路径,路径对象模拟如下:

    public class Path
    {
        public string CurrentNodeId;
        public bool IsProcessed = false;
        public int Weight = 99999999;
        public List<string> PathNodeList = new List<string>();
    }

最短路径计算类:

    ///
    /// 计算最短路径帮助类
    ///
    public class CaculateHelper
    {
        private Dictionary<string, Path>  dicPath = new Dictionary<string, Path>();
        public Dictionary<string, Path> DicPath
        {
            get
            {
                return dicPath;
            }
        }

        public void IniFirstNode(Graph graph, string StartNodeId)
        {
            Node OriginNode = null;
            foreach (Node node in graph.NodeList)
            {
                if (node.Id == StartNodeId)
                {
                    OriginNode = node;
                }
                else
                {
                    Path path = new Path();
                    path.CurrentNodeId = node.Id;
                    dicPath.Add(path.CurrentNodeId, path);  //初始化A->到所有边都是默认的Path 99999999
                }
            }

            //如果有A直接进入的边,则设置为相应权重值,和记录下路径
            foreach (Edge edge in OriginNode.EdgeList)
            {
                Path path = new Path();
                path.CurrentNodeId = edge.EndNodeID;
                path.Weight = edge.Weight;
                path.PathNodeList.Add(edge.StartNodeID);
                dicPath[path.CurrentNodeId] = path;
            }
        }

        public Node GetFromNodeMinWeightNode(Graph graph)
        {
            Node CNode = null;
            KeyValuePair<string, Path> KVPPath = dicPath.Where(m => !m.Value.IsProcessed).OrderBy(m => m.Value.Weight).FirstOrDefault();
            if (KVPPath.Key != null)
            {
                CNode = graph.NodeList.FirstOrDefault(m => m.Id == KVPPath.Value.CurrentNodeId);
            }
            return CNode;
        }

        ///
        /// 计算最短权值路径
        ///
        public void CatelateMinWeightRoad(Graph graph)
        {
            //取从第一个点出发,最小权值且未被访问果的节点的点
            Node CNode = GetFromNodeMinWeightNode(graph);
            //这段代码是核心 循环每个顶点,看看经过该顶点是否会让权值变小,如果会则存起此路径。直到再未访问过的点
            while (CNode != null)
            {
                Path CurrentPath = dicPath[CNode.Id];
                foreach (Edge edge in CNode.EdgeList)
                {
                    Path TargetPath = dicPath[edge.EndNodeID];
                    int tempWeight = CurrentPath.Weight + edge.Weight;
                    if (tempWeight < TargetPath.Weight)
                    {
                        TargetPath.Weight = tempWeight;
                        TargetPath.PathNodeList.Clear();

                        for (int i = 0; i < CurrentPath.PathNodeList.Count; i++)
                        {
                            TargetPath.PathNodeList.Add(CurrentPath.PathNodeList[i].ToString());
                        }

                        TargetPath.PathNodeList.Add(CNode.Id);
                    }
                }

                //标志为已处理
                dicPath[CNode.Id].IsProcessed = true;
                //再次获取权值最小的点
                CNode = GetFromNodeMinWeightNode(graph);
            }
        }
    }

主控制台程序:

class Program
    {
        static void Main(string[] args)
        {
            Graph graph = new Graph();

            #region 初始化一个图的 节点和边

            //***************** B Node *******************
            Node aNode = new Node("A");
            graph.NodeList.Add(aNode);
            //A -> B
            Edge aEdge1 = new Edge();
            aEdge1.StartNodeID = aNode.Id;
            aEdge1.EndNodeID = "B";
            aEdge1.Weight = 10;
            aNode.EdgeList.Add(aEdge1);
            //A -> C
            Edge aEdge2 = new Edge();
            aEdge2.StartNodeID = aNode.Id;
            aEdge2.EndNodeID = "C";
            aEdge2.Weight = 20;
            aNode.EdgeList.Add(aEdge2);
            //A -> E
            Edge aEdge3 = new Edge();
            aEdge3.StartNodeID = aNode.Id;
            aEdge3.EndNodeID = "E";
            aEdge3.Weight = 30;
            aNode.EdgeList.Add(aEdge3);

            //***************** B Node *******************
            Node bNode = new Node("B");
            graph.NodeList.Add(bNode);
            //B -> C
            Edge bEdge1 = new Edge();
            bEdge1.StartNodeID = bNode.Id;
            bEdge1.EndNodeID = "C";
            bEdge1.Weight = 5;
            bNode.EdgeList.Add(bEdge1);
            //B -> E
            Edge bEdge2 = new Edge();
            bEdge2.StartNodeID = bNode.Id;
            bEdge2.EndNodeID = "E";
            bEdge2.Weight = 10;
            bNode.EdgeList.Add(bEdge2);

            //***************** C Node *******************
            Node cNode = new Node("C");
            graph.NodeList.Add(cNode);
            //C -> D
            Edge cEdge1 = new Edge();
            cEdge1.StartNodeID = cNode.Id;
            cEdge1.EndNodeID = "D";
            cEdge1.Weight = 30;
            cNode.EdgeList.Add(cEdge1);

            //***************** D Node *******************
            Node dNode = new Node("D");
            graph.NodeList.Add(dNode);

            //***************** C Node *******************
            Node eNode = new Node("E");
            graph.NodeList.Add(eNode);

            //E -> D
            Edge eEdge1 = new Edge();
            eEdge1.StartNodeID = eNode.Id;
            eEdge1.EndNodeID = "D";
            eEdge1.Weight = 20;
            eNode.EdgeList.Add(eEdge1);

            //E -> F
            Edge eEdge2 = new Edge();
            eEdge2.StartNodeID = eNode.Id;
            eEdge2.EndNodeID = "F";
            eEdge2.Weight = 20;
            eNode.EdgeList.Add(eEdge2);

            //***************** F Node *******************
            Node fNode = new Node("F");
            graph.NodeList.Add(fNode);

            #endregion

            //计算从A -> C的最短权值路线
            string StartNodeId = "A";
            string EndNodeId = "F";

            CaculateHelper CH = new CaculateHelper();
            //第一步,初始化初始化源点 A 到 其他各点的 权重以及 路径(完成 A->B A->C A->E A->D 边权重,与A无直接边的则默认99999999)
            CH.IniFirstNode(graph, StartNodeId);
            //第二步,从权重最小的点开始,一直到权值最大的点
            CH.CatelateMinWeightRoad(graph);

            #region 以下与计算无关,仅仅用于将结果打印出来
            Path ShowPath = CH.DicPath[EndNodeId];
            foreach(string MiddleNodeId in ShowPath.PathNodeList)
            {
                Console.WriteLine(MiddleNodeId);
            }
            Console.WriteLine(ShowPath.Weight);
            #endregion

            Console.ReadKey();
        }
    }

不要小看上面这几行代码,哥看了好久才看懂,如果Node里加几个坐标,就能在地图上面展示了。下一篇会将它改造成可以在地图上面展示的路径规划。

Original: https://www.cnblogs.com/kissdodog/p/5437897.html
Author: 逆心
Title: 带权重的有向图求最短路径

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/552317/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 花一分钟来看看Worktile是如何为团队协作而生的

    团队协作,我们想的更深、更远、更多,花一分钟来看看我们特别奉献的故事,然后去注册一个账号,邀请小伙伴一起来工作,你会体会Worktile才是真正懂你的协作方式。 支持TerryLe…

    技术杂谈 2023年5月31日
    094
  • 区块链代币(Token)笔记 — — 术语

    接触区块链和数字货币差不多有大半年时间,一直在赶项目进度,现在有空整理补习一下相关的知识,只谈代币不谈区块链😂。 声明欢迎转载,但请保留文章原始出处:)博客园:http://www…

    技术杂谈 2023年5月31日
    096
  • SpringBoot自定义环境变量——EnvironmentPostProcessor

    现有需求是将数据库配置文件中账号密码相关信息分离且加密,用到了SpringBoot中 EnvironmentPostProcessor接口。可以将外部配置文件读取注入系统中。 实现…

    技术杂谈 2023年7月24日
    082
  • 用emacs org-mode写cnblogs博客(续)

    3 发文中的博客代码格式背景的问题 在书写博客时,可以使用org自带的 {#+BEGIN_CENTER #+END_CENTER}功能调整文字,图片居中。使用{#+BEGIN_SR…

    技术杂谈 2023年7月25日
    0100
  • Python学习手册——第二部分 类型和运算(1)之数字和字符串

    Python全景 1.程序由模块构成。2.模块包含语句。3.语句包含表达式。4.表达式建立并处理对象。在python中 数据是以 对象的形式出现的!!! 为什么使用内置类型 内置对…

    技术杂谈 2023年7月11日
    096
  • 改Bug的经验

    如果修复某个Bug花了很长时间,这时候就要问问自己为什么,怎么做才吸取经验教训,在类似的问题上不再出问题,以及采用的方法,使用的工具是否还有改进的地方;当所有问题都解决之后,一定要…

    技术杂谈 2023年7月25日
    088
  • R语言—数据基础及练习

    ## 创建leadership数据框 manager ) date "10/24/08","10/28/08","10/1/08&…

    技术杂谈 2023年7月25日
    086
  • 小知识:网站证书过期访问不了怎么办

    今天访问自己的一个网站,www.alfredzhao.cn,居然提示”您的连接不是私密连接”访问不了,自己知道肯定是证书又过期了,但是直接通过http也访问…

    技术杂谈 2023年5月31日
    0117
  • 软件基础的理论(1)

    软件基础的理论 一, 什么是软件产品 它是一个逻辑产品,没有实体,包括程序,文档和数据,需要通过终端设备才能体现出来功能和作用 二, 软件产品的中间过程文档 客户需求 &#…

    技术杂谈 2023年7月25日
    079
  • CAIL2021-阅读理解任务-top3-数据预处理模块

    class SquadExample(object): """ A single training/test example for the Squa…

    技术杂谈 2023年6月1日
    0127
  • Newtonsoft.Json 用法

    忽略某些属性 默认值的处理 空值的处理 支持非公共成员 日期处理 自定义序列化的字段名称 动态决定属性是否序列化 枚举值的自定义格式化问题 自定义类型转换 全局序列化设置 1.忽略…

    技术杂谈 2023年6月1日
    097
  • Python地图栅格化实例

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    技术杂谈 2023年7月24日
    065
  • 分布式锁的三种实现方式

    一、zookeeper 1、实现原理: 基于zookeeper瞬时有序节点实现的分布式锁,其主要逻辑如下(该图来自于IBM网站)。大致思想即为:每个客户端对某个功能加锁时,在zoo…

    技术杂谈 2023年5月31日
    0104
  • C++实现双向RRT算法

    C++实现双向RRT算法 背景介绍 RRT(Rapidly-exploring Random Trees)是Steven M. LaValle和James J. Kuffner J…

    技术杂谈 2023年7月24日
    096
  • Worktile协同特色之一:无处不在的关注

    Worktile选择了更为方便的方式,即引入关注机制,当某个成员与某个任务、文件、讨论、文档有关联时,直接把她添加到关注列表中,或者成员自己也可以主动把自己加入关注列表,这样当任务…

    技术杂谈 2023年5月31日
    096
  • 人生苦短,我用JRebel

    昨天看到团子推送的一篇关于热部署的文章,其中介绍了自研的Sonic插件在公司内部的应用。同时晒出来一张对比图: 团子表示我们的插件要比同类插件优秀哦。不过我定睛一看,好家伙,第一列…

    技术杂谈 2023年7月25日
    075
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球