C# 狄克斯特拉算法

 

    public class Route<T>
    {
        public string FullRoute { get; }

        public Route(Stack<T> stack)
        {
            FullRoute = string.Join(",", stack);
        }
    }

 

 

    public class MyGraph<TNode, TWeight> where TWeight : IComparable<TWeight>
    {
        //节点表
        private readonly Dictionary<TNode, Dictionary<TNode, TWeight>> _nodes;
        //权重表,存储节点最新的权重值
        private readonly Dictionary<TNode, TWeight> _weights;
        //父节点表
        private readonly Dictionary<TNode, TNode> _parents;
        //权重计算委托
        private readonly Func<TWeight, TWeight, TWeight> _weightAddDelegate;
        //已搜索元素的集合
        private HashSet<TNode> _searchedNodes;

        public MyGraph(Dictionary<TNode, Dictionary<TNode, TWeight>> nodes, Dictionary<TNode, TWeight> weights, Dictionary<TNode, TNode> parents, Func<TWeight, TWeight, TWeight> weightAddDelegate)
        {
            _nodes = nodes;
            _weights = weights;
            _parents = parents;
            _weightAddDelegate = weightAddDelegate;
        }


        /// <summary>
        /// 找最小权重
        /// </summary>
        /// <param name="start">起点</param>
        /// <param name="end">终点</param>
        /// <param name="route">路线</param>
        /// <returns></returns>
        public TWeight FindMinWeight(TNode start, TNode end, out Route<TNode> route)
        {
            if (_nodes.ContainsKey(start) == false)
            {
                throw new Exception("not find the start node:" + start);
            }

            if (_nodes.ContainsKey(end) == false)
            {
                throw new Exception("not find the end node:" + end);
            }

            _searchedNodes = new HashSet<TNode>();
            var minWeightNode = FindLowestWeightAndNotSearchedNode();
            while (EqualityComparer<TNode>.Default.Equals(minWeightNode, default) == false)
            {
                //遍历当前节点(minWeightNode)指向的所有节点(item).
                foreach (var item in _nodes[minWeightNode])
                {
                    //计算这些节点的权重
                    //权重 = 这些节点对于当前节点的权重 + 当前节点最新的权重
                    var newWeight = _weightAddDelegate(item.Value, _weights[minWeightNode]);
                    if (newWeight.CompareTo(_weights[item.Key]) > 0)
                    {
                        continue;
                    }
                    //更新权重表和父节点表.
                    _weights[item.Key] = newWeight;
                    _parents[item.Key] = minWeightNode;
                }
                //当前节点搜索完毕后,添加到已搜索集合.
                _searchedNodes.Add(minWeightNode);

                minWeightNode = FindLowestWeightAndNotSearchedNode();
            }

            route = GetRoute(end);
            return _weights[end];
        }

        /// <summary>
        /// 找出权重最小,且还未搜索过的节点.
        /// </summary>
        /// <returns></returns>
        public TNode FindLowestWeightAndNotSearchedNode()
        {
            foreach (var keyValuePair in _weights.OrderBy(o => o.Value))
            {
                if (_searchedNodes.Contains(keyValuePair.Key) == false)
                {
                    return keyValuePair.Key;
                }
            }
            return default;
        }

        /// <summary>
        /// 获取路线
        /// </summary>
        /// <param name="end"></param>
        /// <returns></returns>
        private Route<TNode> GetRoute(TNode end)
        {
            var stack = new Stack<TNode>();
            stack.Push(end);
            TNode node = end;
            while (_parents.TryGetValue(node, out var parent) == true)
            {
                stack.Push(parent);
                node = parent;
            }
            return new Route<TNode>(stack);
        }
    }

 

Test:

            Dictionary<string, Dictionary<string, int>> nodeDic = new Dictionary<string, Dictionary<string, int>>();
            nodeDic.Add("start", new Dictionary<string, int> { { "a", 5 }, { "c", 2 } });
            nodeDic.Add("a", new Dictionary<string, int> { { "b", 4 }, { "d", 4 } });
            nodeDic.Add("b", new Dictionary<string, int> { { "d", 1 }, { "end", 3 } });
            nodeDic.Add("c", new Dictionary<string, int> { { "a", 1 }, { "d", 3 }, { "b", 10 } });
            nodeDic.Add("d", new Dictionary<string, int> { { "end", 8 } });
            nodeDic.Add("end", new Dictionary<string, int>());

            Dictionary<string, int> costDic = new Dictionary<string, int>
            {
                {"a",5 },
                {"c",2 },
                {"b",int.MaxValue },
                {"d",int.MaxValue },
                {"end",int.MaxValue }
            };

            Dictionary<string, string> parentsDic = new Dictionary<string, string>
            {
                {"a","start" },
                {"c","start" },
                {"b",null },
                {"d",null },
                {"end",null },
            };

            Func<int, int, int> @delegate = (x, y) => x + y;
            MyGraph<string, int> g = new MyGraph<string, int>(nodeDic, costDic, parentsDic, @delegate);
            var result = g.FindMinWeight("start", "end", out var route);
            Console.WriteLine(result);
            Console.WriteLine(route.FullRoute);

 

posted @ 2020-07-04 18:27  热敷哥  阅读(262)  评论(0编辑  收藏  举报