Dijkstra算法的最短路径实现

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Collections;
  5. using System.Data;
  6. using System.Data.OleDb;
  7. namespace Dijkstra
  8. {
  9.     class Program
  10.     {
  11.         public class initialization
  12.         {
  13.             public ArrayList initial(DataSet datas)
  14.             {
  15.                 ArrayList al = new ArrayList();
  16.                 #region 初始化
  17.                 for (int i = 0; i < datas.Tables[0].Rows.Count; i++)
  18.                 {
  19.                     DataRow dr = datas.Tables[0].Rows[i];
  20.                     Node tempNode = new Node(dr["NodeName"].ToString());
  21.                     al.Add(tempNode);
  22.                     // DataTable dt = datas.Tables[1].Clone();
  23.                     string strExp = "FromNode = '" + tempNode.ID + "'";
  24.                     DataRow[] dr1 = datas.Tables[1].Select(strExp);
  25.                     if (dr1.Length > 0)
  26.                         for (int j = 0; j < dr1.Length; j++)
  27.                         {
  28.                             Edge tempEdge = new Edge();
  29.                             tempEdge.StartNodeID = tempNode.ID;
  30.                             tempEdge.EndNodeID = dr1[j]["ToNode"].ToString();
  31.                             tempEdge.Weight = (float)dr1[j]["Weight"];
  32.                             tempNode.EdgeList.Add(tempEdge);
  33.                         }
  34.                     else
  35.                         continue;
  36.                 }
  37.                 #endregion
  38.                 return al;
  39.             }
  40.         }
  41.         static void Main(string[] args)
  42.         {
  43.             //初始化
  44.             ArrayList nodeList = new ArrayList();
  45.             //连接数据库
  46.             string constring = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=F://working//NET.mdb";
  47.             OleDbConnection con = new OleDbConnection(constring);
  48.             OleDbDataAdapter adap = new OleDbDataAdapter();
  49.             adap.SelectCommand = new OleDbCommand("SELECT * FROM NodeInfo", con);
  50.             DataSet ds = new DataSet();
  51.             adap.Fill(ds, "NodeInfo");
  52.             adap.SelectCommand = new OleDbCommand("SELECT * FROM RoadInfo", con);
  53.             adap.Fill(ds, "RoadInfo");
  54.             //adap.SelectCommand = new OleDbCommand("SELECT * FROM BusLine", con);
  55.             //adap.Fill(ds, "BusLine");
  56.             initialization init = new initialization();
  57.             nodeList = init.initial(ds);
  58.             con.Close();
  59.             Console.WriteLine("The total Node is A,B,C,D,E");
  60.             Console.WriteLine("Please input original node");
  61.             string origin, destination;
  62.             origin = Console.ReadLine();
  63.             int tag = 0;
  64.             while (tag == 0)
  65.             {
  66.                 for (int int1 = 0; int1 < ds.Tables[0].Rows.Count; int1++)
  67.                 {
  68.                     DataRow datarow1 = ds.Tables[0].Rows[int1];
  69.                     if (origin == datarow1["NodeName"].ToString())
  70.                         tag = 1;
  71.                 }
  72.                 if (tag == 0)
  73.                 {
  74.                     Console.WriteLine("This origin node is wrong, please input again!");
  75.                     origin = Console.ReadLine();
  76.                 }
  77.             }
  78.             Console.WriteLine("Please input destination node");
  79.             destination = Console.ReadLine();
  80.             int tag2 = 0;
  81.             for (int int2 = 0; int2 < ds.Tables[0].Rows.Count; int2++)
  82.             {
  83.                 DataRow datarow2 = ds.Tables[0].Rows[int2];
  84.                 if (origin == datarow2["NodeName"].ToString())
  85.                     tag2 = 1;
  86.             }
  87.             if (tag2 == 0)
  88.             {
  89.                 Console.WriteLine("This destination node is wrong, please input again!");
  90.                 destination = Console.ReadLine();
  91.             }
  92.             RoutePlanner planner = new RoutePlanner();
  93.             RoutePlanResult result = planner.Paln(nodeList, origin, destination);
  94.             Console.WriteLine("最少公交站路线:");
  95.             foreach (string node in result.passedNodeIDs)
  96.             {
  97.                 Console.Write(node);
  98.                 Console.Write("->");
  99.             }
  100.             Console.WriteLine(destination);
  101.             Console.WriteLine("经过的公交站数为: " + result.weight.ToString());
  102.             planner = null;
  103.         }
  104.         public class Edge
  105.         {
  106.             public string StartNodeID;
  107.             public string EndNodeID;
  108.             public double Weight; //权值,代价        
  109.         }
  110.         public class Node
  111.         {
  112.             private string iD;
  113.             private ArrayList edgeList;//Edge的集合--出边表
  114.             public Node(string id)
  115.             {
  116.                 this.iD = id;
  117.                 this.edgeList = new ArrayList();
  118.             }
  119.             #region property
  120.             public string ID
  121.             {
  122.                 get
  123.                 {
  124.                     return this.iD;
  125.                 }
  126.             }
  127.             public ArrayList EdgeList
  128.             {
  129.                 get
  130.                 {
  131.                     return this.edgeList;
  132.                 }
  133.             }
  134.             #endregion
  135.         }
  136.         /// <summary>
  137.         /// PassedPath 用于暂存计算过程中的到达某个节点的权值最小的路径
  138.         /// </summary>
  139.         public class PassedPath
  140.         {
  141.             private string curNodeID;
  142.             private bool beProcessed;   //是否已被处理
  143.             private double weight;        //累积的权值
  144.             private ArrayList passedIDList; //路径
  145.             public PassedPath(string ID)
  146.             {
  147.                 this.curNodeID = ID;
  148.                 this.weight = double.MaxValue;
  149.                 this.passedIDList = new ArrayList();
  150.                 this.beProcessed = false;
  151.             }
  152.             #region property
  153.             public bool BeProcessed
  154.             {
  155.                 get
  156.                 {
  157.                     return this.beProcessed;
  158.                 }
  159.                 set
  160.                 {
  161.                     this.beProcessed = value;
  162.                 }
  163.             }
  164.             public string CurNodeID
  165.             {
  166.                 get
  167.                 {
  168.                     return this.curNodeID;
  169.                 }
  170.             }
  171.             public double Weight
  172.             {
  173.                 get
  174.                 {
  175.                     return this.weight;
  176.                 }
  177.                 set
  178.                 {
  179.                     this.weight = value;
  180.                 }
  181.             }
  182.             public ArrayList PassedIDList
  183.             {
  184.                 get
  185.                 {
  186.                     return this.passedIDList;
  187.                 }
  188.             }
  189.             #endregion
  190.         }
  191.         /// <summary>
  192.         /// PlanCourse 暂存从起始点到其它任一节点的最小权值路径=》路径表
  193.         /// </summary>
  194.         public class PlanCourse
  195.         {
  196.             private Hashtable htPassedPath;
  197.             #region ctor
  198.             public PlanCourse(ArrayList nodeList, string originID)
  199.             {
  200.                 this.htPassedPath = new Hashtable();
  201.                 Node originNode = null;
  202.                 foreach (Node node in nodeList)
  203.                 {
  204.                     if (node.ID == originID)
  205.                     {
  206.                         originNode = node;
  207.                     }
  208.                     else
  209.                     {
  210.                         PassedPath pPath = new PassedPath(node.ID);
  211.                         this.htPassedPath.Add(node.ID, pPath);
  212.                     }
  213.                 }
  214.                 if (originNode == null)
  215.                 {
  216.                     throw new Exception("The origin node is not exist !");
  217.                 }
  218.                 this.InitializeWeight(originNode);
  219.             }
  220.             private void InitializeWeight(Node originNode)
  221.             {
  222.                 if ((originNode.EdgeList == null) || (originNode.EdgeList.Count == 0))
  223.                 {
  224.                     return;
  225.                 }
  226.                 foreach (Edge edge in originNode.EdgeList)
  227.                 {
  228.                     PassedPath pPath = this[edge.EndNodeID];
  229.                     if (pPath == null)
  230.                     {
  231.                         continue;
  232.                     }
  233.                     pPath.PassedIDList.Add(originNode.ID);
  234.                     pPath.Weight = edge.Weight;
  235.                 }
  236.             }
  237.             #endregion
  238.             public PassedPath this[string nodeID]
  239.             {
  240.                 get
  241.                 {
  242.                     return (PassedPath)this.htPassedPath[nodeID];
  243.                 }
  244.             }
  245.         }
  246.         /// <summary>
  247.         /// RoutePlanResult 
  248.         /// </summary>
  249.         public class RoutePlanResult
  250.         {
  251.             public string[] passedNodeIDs;
  252.             public double weight;
  253.             public RoutePlanResult(string[] strings, double d)
  254.             {
  255.                 this.passedNodeIDs = strings;
  256.                 this.weight = d;
  257.             }
  258.             public string[] getPassedNodeIDs()
  259.             {
  260.                 return passedNodeIDs;
  261.             }
  262.             public void setPassedNodeIDs(string[] passedNodeIDs)
  263.             {
  264.                 this.passedNodeIDs = passedNodeIDs;
  265.             }
  266.             public double getWeight()
  267.             {
  268.                 return weight;
  269.             }
  270.             public void setWeight(double weight)
  271.             {
  272.                 this.weight = weight;
  273.             }
  274.         }
  275.         /// <summary>
  276.         /// RoutePlanner 提供图算法中常用的路径规划功能。
  277.         /// 2008.10.15
  278.         /// </summary>
  279.         public class RoutePlanner
  280.         {
  281.             public RoutePlanner()
  282.             {
  283.             }
  284.             #region Paln
  285.             //获取权值最小的路径
  286.             public RoutePlanResult Paln(ArrayList nodeList, string originID, string destID)
  287.             {
  288.                 PlanCourse planCourse = new PlanCourse(nodeList, originID);
  289.                 Node curNode = this.GetMinWeightRudeNode(planCourse, nodeList, originID);
  290.                 #region 计算过程
  291.                 while (curNode != null)
  292.                 {
  293.                     PassedPath curPath = planCourse[curNode.ID];
  294.                     foreach (Edge edge in curNode.EdgeList)
  295.                     {
  296.                         if (edge.EndNodeID == originID)
  297.                             continue;
  298.                         PassedPath targetPath = planCourse[edge.EndNodeID];
  299.                         double tempWeight = curPath.Weight + edge.Weight;
  300.                         if (tempWeight < targetPath.Weight)
  301.                         {
  302.                             targetPath.Weight = tempWeight;
  303.                             targetPath.PassedIDList.Clear();
  304.                             for (int i = 0; i < curPath.PassedIDList.Count; i++)
  305.                             {
  306.                                 targetPath.PassedIDList.Add(curPath.PassedIDList[i].ToString());
  307.                             }
  308.                             targetPath.PassedIDList.Add(curNode.ID);
  309.                         }
  310.                     }
  311.                     //标志为已处理
  312.                     planCourse[curNode.ID].BeProcessed = true;
  313.                     //获取下一个未处理节点
  314.                     curNode = this.GetMinWeightRudeNode(planCourse, nodeList, originID);
  315.                 }
  316.                 #endregion
  317.                 //表示规划结束
  318.                 return this.GetResult(planCourse, destID);
  319.             }
  320.             #endregion
  321.             #region private method
  322.             #region GetResult
  323.             //从PlanCourse表中取出目标节点的PassedPath,这个PassedPath即是规划结果
  324.             private RoutePlanResult GetResult(PlanCourse planCourse, string destID)
  325.             {
  326.                 PassedPath pPath = planCourse[destID];
  327.                 if (pPath.Weight == int.MaxValue)
  328.                 {
  329.                     RoutePlanResult result1 = new RoutePlanResult(nullint.MaxValue);
  330.                     return result1;
  331.                 }
  332.                 string[] passedNodeIDs = new string[pPath.PassedIDList.Count];
  333.                 for (int i = 0; i < passedNodeIDs.Length; i++)
  334.                 {
  335.                     passedNodeIDs[i] = pPath.PassedIDList[i].ToString();
  336.                 }
  337.                 RoutePlanResult result = new RoutePlanResult(passedNodeIDs, pPath.Weight);
  338.                 return result;
  339.             }
  340.             #endregion
  341.             #region GetMinWeightRudeNode
  342.             //从PlanCourse取出一个当前累积权值最小,并且没有被处理过的节点
  343.             private Node GetMinWeightRudeNode(PlanCourse planCourse, ArrayList nodeList, string originID)
  344.             {
  345.                 double weight = double.MaxValue;
  346.                 Node destNode = null;
  347.                 foreach (Node node in nodeList)
  348.                 {
  349.                     if (node.ID == originID)
  350.                     {
  351.                         continue;
  352.                     }
  353.                     PassedPath pPath = planCourse[node.ID];
  354.                     if (pPath.BeProcessed)
  355.                     {
  356.                         continue;
  357.                     }
  358.                     if (pPath.Weight < weight)
  359.                     {
  360.                         weight = pPath.Weight;
  361.                         destNode = node;
  362.                     }
  363.                 }
  364.                 return destNode;
  365.             }
  366.             #endregion
  367.             #endregion
  368.         }
  369.     }
  370. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dijkstra算法是一种用于解决单源最短路径问题的算法。它通过贪婪地选择当前最短路径来逐步构建最短路径树。以下是Dijkstra算法的步骤: 1. 创建一个空的最短路径集合,用于存储从起始节点到其他节点的最短路径。 2. 初始化起始节点的最短路径为0,将其添加到最短路径集合。 3. 对于起始节点的所有邻居节点,更新它们的最短路径值。如果通过当前节点到达邻居节点的路径比已知的最短路径更短,则更新最短路径值。 4. 从未添加到最短路径集合的节点选择一个具有最小最短路径值的节点,并将其添加到最短路径集合。 5. 重复步骤3和步骤4,直到所有节点都被添加到最短路径集合。 6. 最终,最短路径集合存储了从起始节点到所有其他节点的最短路径Dijkstra算法的特点和限制如下: - Dijkstra算法仅适用于非负权重的图,因为它依赖于贪婪策略来选择当前最短路径。 - 它可以找到从起始节点到所有其他节点的最短路径,因此适用于单源最短路径问题。 - Dijkstra算法不会处理负权边,如果图存在负权边,应该使用其他算法,如Bellman-Ford算法。 - 算法的时间复杂度取决于数据结构的选择,一般情况下是O(V^2)或O(Vlog(V)),其V是节点数。如果使用优先队列来优化,时间复杂度可以减小到O(Elog(V)),其E是边数。 以下是一个使用Dijkstra算法找到最短路径的示例代码: ```python import sys def dijkstra(graph, start): # 初始化最短路径集合和最短路径字典 shortest_paths = {node: sys.maxsize for node in graph} shortest_paths[start] = 0 visited = set() while len(visited) < len(graph): # 选择当前最短路径值的节点 current_node = min((node for node in graph if node not in visited), key=lambda node: shortest_paths[node]) visited.add(current_node) # 更新邻居节点的最短路径值 for neighbor in graph[current_node]: distance = shortest_paths[current_node] + graph[current_node][neighbor] if distance < shortest_paths[neighbor]: shortest_paths[neighbor] = distance return shortest_paths # 示例图的邻接表表示 graph = { 'A': {'B': 5, 'C': 3}, 'B': {'A': 5, 'C': 1, 'D': 3}, 'C': {'A': 3, 'B': 1, 'D': 2, 'E': 6}, 'D': {'B': 3, 'C': 2, 'E': 4, 'F': 2}, 'E': {'C': 6, 'D': 4, 'F': 6}, 'F': {'D': 2, 'E': 6} } start_node = 'A' shortest_paths = dijkstra(graph, start_node) for node in shortest_paths: print(f"Shortest path from {start_node} to {node}: {shortest_paths[node]}") ``` 这段代码使用邻接表表示图,并从起始节点'A'开始找到到达其他节点的最短路径。最终,它会输出从起始节点到每个节点的最短路径值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值