zoukankan      html  css  js  c++  java
  • C#迪杰斯特拉算法

    C#迪杰斯特拉算法##

    网上有许多版本的,自己还是写一个理解点

    Dijkstra.cs

    public class Dijkstra
    	{
    		private List<Node> _nodes;
    		private List<Edge> _edges;
    
    		public Dijkstra()
    		{
    			_nodes = new List<Node>();
    			_edges = new List<Edge>();
    		}
    
    		public void InitWeights(List<Tuple<string, string, double>> weights)
    		{
    			_edges = ConvertToEdge(weights);
    
    			InitNodes();
    		}
    
    		public List<string> Find(string start, string end)
    		{
    			var startNode = GetNodeByName(start);
    			var endNode = GetNodeByName(end);
    
    			if (startNode == null || endNode == null)
    			{
    				return new List<string>();
    			}
    
    			var s = _nodes.Where(x => x.Name == start).ToList();
    			var u = _nodes.Where(x => x.Name != start).ToList();
    
    			s.ForEach(x =>
    			{
    				x.Weight = 0;
    			});
    
    			u.ForEach(x =>
    			{
    				x.Weight = double.PositiveInfinity;
    			});
    
    			while (u.Any())
    			{
    				var node = s.Last();
    
    				//更新node到x的距离
    				u.ForEach(x =>
    				{
    					var edge = GetEdgeByTwoNode(node, x);
    
    					if (edge != null)
    					{
    						var weights = node.GetAllWeight() + edge.Weight;
    
    						if (weights < x.Weight)
    						{
    							x.Weight = weights;
    							x.Parent = node;
    						}
    					}
    				});
    
    				//找出距离最小的
    				var minNode = u.OrderBy(x => x.Weight).FirstOrDefault();
    
    				s.Add(minNode);
    				u.Remove(minNode);
    			}
    
    			var paths = new Stack<string>();
    
    			while (endNode != null)
    			{
    				paths.Push(endNode.Name);
    				endNode = endNode.Parent;
    			}
    
    			//如果路劲中包含起点
    			if (paths.ToList().Contains(start))
    			{
    				return paths.ToList();
    			}
    			else
    			{
    				return new List<string>();
    			}
    		}
    
    		private Edge GetEdgeByTwoNode(Node start, Node end)
    		{
    			var edge = _edges.FirstOrDefault(x => x.Start == start.Name && x.End == end.Name);
    
    			if (edge == null)
    			{
    				edge = _edges.FirstOrDefault(x => x.Start == end.Name && x.End == start.Name);
    			}
    
    			return edge;
    		}
    
    		/// <summary>
    		/// 将权值转换成边
    		/// </summary>
    		/// <returns></returns>
    		private List<Edge> ConvertToEdge(List<Tuple<string, string, double>> weights)
    		{
    			var edges = new List<Edge>();
    
    			weights.ForEach(weight =>
    			{
    				edges.Add(new Edge()
    				{
    					Start = weight.Item1,
    					End = weight.Item2,
    					Weight = weight.Item3
    				});
    			});
    
    			return edges;
    		}
    
    
    		/// <summary>
    		/// 根据名字获取节点
    		/// </summary>
    		/// <param name="nodeName"></param>
    		/// <returns></returns>
    		private Node GetNodeByName(string nodeName)
    		{
    			return _nodes.FirstOrDefault(x => x.Name == nodeName);
    		}
    
    		/// <summary>
    		/// 初始化点
    		/// </summary>
    		private void InitNodes()
    		{
    			_edges.ForEach(weight =>
    			{
    				if (_nodes.All(x => x.Name != weight.Start))
    				{
    					_nodes.Add(new Node()
    					{
    						Name = weight.Start
    					});
    				}
    
    				if (_nodes.All(x => x.Name != weight.End))
    				{
    					_nodes.Add(new Node()
    					{
    						Name = weight.End
    					});
    				}
    			});
    		}
    	}
    

    Edge.cs

    //表示一条边,从Start到End的权值为多少
    	internal class Edge
    	{
    		public string Start
    		{
    			get; set;
    		}
    
    		public string End
    		{
    			get; set;
    		}
    
    		public double Weight
    		{
    			get; set;
    		}
    	}
    

    Node.cs

    internal class Node
    	{
    		public string Name
    		{
    			get; set;
    		}
    
    		public Node Parent
    		{
    			get; set;
    		}
    
    		/// <summary>
    		/// 该节点到起点的最短距离
    		/// </summary>
    		public double Weight
    		{
    			get; set;
    		}
    
    		public double GetAllWeight()
    		{
    			var allWeight = 0d;
    
    			var node = this;
    
    			do
    			{
    				allWeight += node.Weight;
    
    				node = node.Parent;
    
    			} while (node != null);
    
    			return allWeight;
    		}
    	}
    

    使用如下

    static void Main(string[] args)
    		{
    			var weights = new List<Tuple<string, string, double>>()
    			{
    			new Tuple<string,string,double>("A","B",12),
    			new Tuple<string,string,double>("A","F",16),
    			new Tuple<string,string,double>("A","G",14),
    			new Tuple<string,string,double>("B","F",7),
    			new Tuple<string,string,double>("B","C",10),
    			new Tuple<string,string,double>("G","F",9),
    			new Tuple<string,string,double>("G","E",8),
    			new Tuple<string,string,double>("F","C",6),
    			new Tuple<string,string,double>("F","E",2),
    			new Tuple<string,string,double>("C","D",3),
    			new Tuple<string,string,double>("C","E",5),
    			new Tuple<string,string,double>("E","D",4),
    			};
    
    			var dij = new Dijkstra();
    
    			dij.InitWeights(weights);
    
    			var path = dij.Find("D", "G");
    
    			path.ForEach(Console.WriteLine);
    		}
  • 相关阅读:
    人为什么会生气 --- 答案是什么?
    职场中我们常犯的8个错误
    职场上最常见的20条错误,犯三条就够致命啦
    C语言,基于单向链表实现,变长动态数据缓冲区(线程安全) ---- 类似java的StringBuffer --- 亲测OK
    门限签名
    基于RSA的实用门限签名算法
    图解密码技术(第3版)-第4章
    各种加密算法比较
    密码那点事儿
    数字签名,我有疑问。
  • 原文地址:https://www.cnblogs.com/HelloMyWorld/p/5049658.html
Copyright © 2011-2022 走看看