算法系列15天速成——第十五天 图【下】(大结局)

16 篇文章 0 订阅

算法系列15天速成——第十五天 图【下】(大结局)


转自:http://blog.csdn.net/m13666368773/article/details/7530397


今天是大结局,说下“图”的最后一点东西,“最小生成树“和”最短路径“。

 

一: 最小生成树

1. 概念

    首先看如下图,不知道大家能总结点什么。

    对于一个连通图G,如果其全部顶点和一部分边构成一个子图G1,当G1满足:

       ① 刚好将图中所有顶点连通。②顶点不存在回路。则称G1就是G的“生成树”。

           其实一句话总结就是:生成树是将原图的全部顶点以最小的边连通的子图,这不,如下的连通图可以得到下面的两个生成树。

       ② 对于一个带权的连通图,当生成的树不同,各边上的权值总和也不同,如果某个生成树的权值最小,则它就是“最小生成树”。

     

2. 场景

      实际应用中“最小生成树”还是蛮有实际价值的,教科书上都有这么一句话,若用图来表示一个交通系统,每一个顶点代表一个城市,

  边代表两个城市之间的距离,当有n个城市时,可能会有n(n-1)/2条边,那么怎么选择(n-1)条边来使城市之间的总距离最小,其实它

  的抽象模型就是求“最小生成树”的问题。

 

3. prim算法

    当然如何求“最小生成树”问题,前人都已经给我们总结好了,我们只要照葫芦画瓢就是了,

    第一步:我们建立集合“V,U",将图中的所有顶点全部灌到V集合中,U集合初始为空。

    第二步: 我们将V1放入U集合中并将V1顶点标记为已访问。此时:U(V1)。

    第三步: 我们寻找V1的邻接点(V2,V3,V5),权值中发现(V1,V2)之间的权值最小,此时我们将V2放入U集合中并标记V2为已访问,

                此时为U(V1,V2)。

    第四步: 我们找U集合中的V1和V2的邻接边,一阵痉挛后,发现(V1,V5)的权值最小,此时将V5加入到U集合并标记为已访问,此时

                 U的集合元素为(V1,V2,V5)。

    第五步:此时我们以(V1,V2,V5)为基准向四周寻找最小权值的邻接边,发现(V5,V4)的权值最小,此时将V4加入到U集合并标记

                 为已访问,此时U的集合元素为(V1,V2,V5,V4)。

    第六步: 跟第五步形式一样,找到了(V1,V3)的权值最小,将V3加入到U集合中并标记为已访问,最终U的元素为(V1,V2,V5,V4,V3),

                最终发现顶点全部被访问,最小生成树就此诞生。

复制代码
[csharp] view plain copy
  1. #region prim算法获取最小生成树  
  2.          /// <summary>  
  3.  /// prim算法获取最小生成树  
  4.  /// </summary>  
  5.  /// <param name="graph"></param>  
  6.          public void Prim(MatrixGraph graph, out int sum)  
  7.          {  
  8.              //已访问过的标志  
  9.              int used = 0;  
  10.    
  11.              //非邻接顶点标志  
  12.              int noadj = -1;  
  13.    
  14.              //定义一个输出总权值的变量  
  15.              sum = 0;  
  16.    
  17.              //临时数组,用于保存邻接点的权值  
  18.              int[] weight = new int[graph.vertexNum];  
  19.    
  20.              //临时数组,用于保存顶点信息  
  21.              int[] tempvertex = new int[graph.vertexNum];  
  22.    
  23.              //取出邻接矩阵的第一行数据,也就是取出第一个顶点并将权和边信息保存于临时数据中  
  24.              for (int i = 1; i < graph.vertexNum; i++)  
  25.              {  
  26.                  //保存于邻接点之间的权值  
  27.                  weight[i] = graph.edges[0, i];  
  28.    
  29.                  //等于0则说明V1与该邻接点没有边  
  30.                  if (weight[i] == short.MaxValue)  
  31.                      tempvertex[i] = noadj;  
  32.                  else  
  33.                      tempvertex[i] = int.Parse(graph.vertex[0]);  
  34.              }  
  35.    
  36.              //从集合V中取出V1节点,只需要将此节点设置为已访问过,weight为0集合  
  37.              var index = tempvertex[0] = used;  
  38.              var min = weight[0] = short.MaxValue;  
  39.    
  40.              //在V的邻接点中找权值最小的节点  
  41.              for (int i = 1; i < graph.vertexNum; i++)  
  42.              {  
  43.                  index = i;  
  44.                  min = short.MaxValue;  
  45.    
  46.                  for (int j = 1; j < graph.vertexNum; j++)  
  47.                  {  
  48.                      //用于找出当前节点的邻接点中权值最小的未访问点  
  49.                      if (weight[j] < min && tempvertex[j] != 0)  
  50.                      {  
  51.                          min = weight[j];  
  52.                          index = j;  
  53.                      }  
  54.                  }  
  55.                  //累加权值  
  56.                  sum += min;  
  57.    
  58.                  Console.Write("({0},{1})  ", tempvertex[index], graph.vertex[index]);  
  59.    
  60.                  //将取得的最小节点标识为已访问  
  61.                  weight[index] = short.MaxValue;  
  62.                  tempvertex[index] = 0;  
  63.    
  64.                  //从最新的节点出发,将此节点的weight比较赋值  
  65.                  for (int j = 0; j < graph.vertexNum; j++)  
  66.                  {  
  67.                      //已当前节点为出发点,重新选择最小边  
  68.                      if (graph.edges[index, j] < weight[j] && tempvertex[j] != used)  
  69.                      {  
  70.                          weight[j] = graph.edges[index, j];  
  71.    
  72.                          //这里做的目的将较短的边覆盖点上一个节点的邻接点中的较长的边  
  73.                          tempvertex[j] = int.Parse(graph.vertex[index]);  
  74.                      }  
  75.                  }  
  76.              }  
  77.          }  
  78.          #endregion  


二: 最短路径

1.   概念

        求最短路径问题其实也是非常有实用价值的,映射到交通系统图中,就是求两个城市间的最短路径问题,还是看这张图,我们可以很容易的看出比如

     V1到图中各顶点的最短路径。

      ① V1  ->  V2              直达,     权为2。

      ② V1  ->  V3              直达        权为3。

      ③ V1->V5->V4           中转       权为3+2=5。

      ④ V1  ->  V5               直达      权为3。

  

2.  Dijkstra算法

      我们的学习需要站在巨人的肩膀上,那么对于现实中非常复杂的问题,我们肯定不能用肉眼看出来,而是根据一定的算法推导出来的。

  Dijkstra思想遵循 “走一步,看一步”的原则。

     第一步: 我们需要一个集合U,然后将V1放入U集合中,既然走了一步,我们就要看一步,就是比较一下V1的邻接点(V2,V3,V5),

                 发现(V1,V2)的权值最小,此时我们将V2放入U集合中,表示我们已经找到了V1到V2的最短路径。

     第二步:然后将V2做中间点,继续向前寻找权值最小的邻接点,发现只有V4可以连通,此时修改V4的权值为(V1,V2)+(V2,V4)=6。

                此时我们就要看一步,发现V1到(V3,V4,V5)中权值最小的是(V1,V5),此时将V5放入U集合中,表示我们已经找到了

                V1到V5的最短路径。

     第三步:然后将V5做中间点,继续向前寻找权值最小的邻接点,发现能连通的有V3,V4,当我们正想修该V3的权值时发现(V1,V3)的权值

                小于(V1->V5->V3),此时我们就不修改,将V3放入U集合中,最后我们找到了V1到V3的最短路径。

     第四步:因为V5还没有走完,所以继续用V5做中间点,此时只能连通(V5,V4),当要修改权值的时候,发现原来的V4权值为(V1,V2)+(V2,V4),而

                现在的权值为5,小于先前的6,此时更改原先的权值变为5,将V4放入集合中,最后我们找到了V1到V4的最短路径。

 

复制代码
[csharp] view plain copy
  1. #region dijkstra求出最短路径  
  2.          /// <summary>  
  3.  /// dijkstra求出最短路径  
  4.  /// </summary>  
  5.  /// <param name="g"></param>  
  6.          public void Dijkstra(MatrixGraph g)  
  7.          {  
  8.              int[] weight = new int[g.vertexNum];  
  9.    
  10.              int[] path = new int[g.vertexNum];  
  11.    
  12.              int[] tempvertex = new int[g.vertexNum];  
  13.    
  14.              Console.WriteLine("\n请输入源点的编号:");  
  15.    
  16.              //让用户输入要遍历的起始点  
  17.              int vertex = int.Parse(Console.ReadLine()) - 1;  
  18.    
  19.              for (int i = 0; i < g.vertexNum; i++)  
  20.              {  
  21.                  //初始赋权值  
  22.                  weight[i] = g.edges[vertex, i];  
  23.    
  24.                  if (weight[i] < short.MaxValue && weight[i] > 0)  
  25.                      path[i] = vertex;  
  26.    
  27.                  tempvertex[i] = 0;  
  28.              }  
  29.    
  30.              tempvertex[vertex] = 1;  
  31.              weight[vertex] = 0;  
  32.    
  33.              for (int i = 0; i < g.vertexNum; i++)  
  34.              {  
  35.                  int min = short.MaxValue;  
  36.    
  37.                  int index = vertex;  
  38.    
  39.                  for (int j = 0; j < g.vertexNum; j++)  
  40.                  {  
  41.                      //顶点的权值中找出最小的  
  42.                      if (tempvertex[j] == 0 && weight[j] < min)  
  43.                      {  
  44.                          min = weight[j];  
  45.                          index = j;  
  46.                      }  
  47.                  }  
  48.    
  49.                  tempvertex[index] = 1;  
  50.    
  51.                  //以当前的index作为中间点,找出最小的权值  
  52.                  for (int j = 0; j < g.vertexNum; j++)  
  53.                  {  
  54.                      if (tempvertex[j] == 0 && weight[index] + g.edges[index, j] < weight[j])  
  55.                      {  
  56.                          weight[j] = weight[index] + g.edges[index, j];  
  57.                          path[j] = index;  
  58.                      }  
  59.                  }  
  60.              }  
  61.    
  62.              Console.WriteLine("\n顶点{0}到各顶点的最短路径为:(终点 < 源点) " + g.vertex[vertex]);  
  63.    
  64.              //最后输出  
  65.              for (int i = 0; i < g.vertexNum; i++)  
  66.              {  
  67.                  if (tempvertex[i] == 1)  
  68.                  {  
  69.                      var index = i;  
  70.    
  71.                      while (index != vertex)  
  72.                      {  
  73.                          var j = index;  
  74.                          Console.Write("{0} < ", g.vertex[index]);  
  75.                          index = path[index];  
  76.                      }  
  77.                      Console.WriteLine("{0}\n", g.vertex[index]);  
  78.                  }  
  79.                  else  
  80.                  {  
  81.                      Console.WriteLine("{0} <- {1}: 无路径\n", g.vertex[i], g.vertex[vertex]);  
  82.                  }  
  83.              }  
  84.          }  
  85.          #endregion  



最后上一下总的运行代码

[csharp] view plain copy
  1. View Code   
  2.  using System;  
  3.  using System.Collections.Generic;  
  4.  using System.Linq;  
  5.  using System.Text;  
  6.    
  7.  namespace MatrixGraph  
  8.  {  
  9.      public class Program  
  10.      {  
  11.          static void Main(string[] args)  
  12.          {  
  13.              MatrixGraphManager manager = new MatrixGraphManager();  
  14.    
  15.              //创建图  
  16.              MatrixGraph graph = manager.CreateMatrixGraph();  
  17.    
  18.              manager.OutMatrix(graph);  
  19.    
  20.              int sum = 0;  
  21.    
  22.              manager.Prim(graph, out sum);  
  23.    
  24.              Console.WriteLine("\n最小生成树的权值为:" + sum);  
  25.    
  26.              manager.Dijkstra(graph);  
  27.    
  28.              //Console.Write("广度递归:\t");  
  29.    
  30.  //manager.BFSTraverse(graph);  
  31.    
  32.  //Console.Write("\n深度递归:\t");  
  33.    
  34.  //manager.DFSTraverse(graph);  
  35.    
  36.              Console.ReadLine();  
  37.    
  38.          }  
  39.      }  
  40.   
  41.      #region 邻接矩阵的结构图  
  42.      /// <summary>  
  43.  /// 邻接矩阵的结构图  
  44.  /// </summary>  
  45.      public class MatrixGraph  
  46.      {  
  47.          //保存顶点信息  
  48.          public string[] vertex;  
  49.    
  50.          //保存边信息  
  51.          public int[,] edges;  
  52.    
  53.          //深搜和广搜的遍历标志  
  54.          public bool[] isTrav;  
  55.    
  56.          //顶点数量  
  57.          public int vertexNum;  
  58.    
  59.          //边数量  
  60.          public int edgeNum;  
  61.    
  62.          //图类型  
  63.          public int graphType;  
  64.    
  65.          /// <summary>  
  66.  /// 存储容量的初始化  
  67.  /// </summary>  
  68.  /// <param name="vertexNum"></param>  
  69.  /// <param name="edgeNum"></param>  
  70.  /// <param name="graphType"></param>  
  71.          public MatrixGraph(int vertexNum, int edgeNum, int graphType)  
  72.          {  
  73.              this.vertexNum = vertexNum;  
  74.              this.edgeNum = edgeNum;  
  75.              this.graphType = graphType;  
  76.    
  77.              vertex = new string[vertexNum];  
  78.              edges = new int[vertexNum, vertexNum];  
  79.              isTrav = new bool[vertexNum];  
  80.          }  
  81.    
  82.      }  
  83.      #endregion  
  84.    
  85.      /// <summary>  
  86.  /// 图的操作类  
  87.  /// </summary>  
  88.      public class MatrixGraphManager  
  89.      {  
  90.          #region 图的创建  
  91.          /// <summary>  
  92.  /// 图的创建  
  93.  /// </summary>  
  94.  /// <param name="g"></param>  
  95.          public MatrixGraph CreateMatrixGraph()  
  96.          {  
  97.              Console.WriteLine("请输入创建图的顶点个数,边个数,是否为无向图(0,1来表示),已逗号隔开。");  
  98.    
  99.              var initData = Console.ReadLine().Split(',').Select(i => int.Parse(i)).ToList();  
  100.    
  101.              MatrixGraph graph = new MatrixGraph(initData[0], initData[1], initData[2]);  
  102.    
  103.              //我们默认“正无穷大为没有边”  
  104.              for (int i = 0; i < graph.vertexNum; i++)  
  105.              {  
  106.                  for (int j = 0; j < graph.vertexNum; j++)  
  107.                  {  
  108.                      graph.edges[i, j] = short.MaxValue;  
  109.                  }  
  110.              }  
  111.    
  112.              Console.WriteLine("请输入各顶点信息:");  
  113.    
  114.              for (int i = 0; i < graph.vertexNum; i++)  
  115.              {  
  116.                  Console.Write("\n第" + (i + 1) + "个顶点为:");  
  117.    
  118.                  var single = Console.ReadLine();  
  119.    
  120.                  //顶点信息加入集合中  
  121.                  graph.vertex[i] = single;  
  122.              }  
  123.    
  124.              Console.WriteLine("\n请输入构成两个顶点的边和权值,以逗号隔开。\n");  
  125.    
  126.              for (int i = 0; i < graph.edgeNum; i++)  
  127.              {  
  128.                  Console.Write("第" + (i + 1) + "条边:\t");  
  129.    
  130.                  initData = Console.ReadLine().Split(',').Select(j => int.Parse(j)).ToList();  
  131.    
  132.                  int start = initData[0];  
  133.                  int end = initData[1];  
  134.                  int weight = initData[2];  
  135.    
  136.                  //给矩阵指定坐标位置赋值  
  137.                  graph.edges[start - 1, end - 1] = weight;  
  138.    
  139.                  //如果是无向图,则数据呈“二,四”象限对称  
  140.                  if (graph.graphType == 1)  
  141.                  {  
  142.                      graph.edges[end - 1, start - 1] = weight;  
  143.                  }  
  144.              }  
  145.    
  146.              return graph;  
  147.          }  
  148.          #endregion  
  149.   
  150.          #region 输出矩阵数据  
  151.          /// <summary>  
  152.  /// 输出矩阵数据  
  153.  /// </summary>  
  154.  /// <param name="graph"></param>  
  155.          public void OutMatrix(MatrixGraph graph)  
  156.          {  
  157.              for (int i = 0; i < graph.vertexNum; i++)  
  158.              {  
  159.                  for (int j = 0; j < graph.vertexNum; j++)  
  160.                  {  
  161.                      if (graph.edges[i, j] == short.MaxValue)  
  162.                          Console.Write("∽\t");  
  163.                      else  
  164.                          Console.Write(graph.edges[i, j] + "\t");  
  165.                  }  
  166.                  //换行  
  167.                  Console.WriteLine();  
  168.              }  
  169.          }  
  170.          #endregion  
  171.   
  172.          #region 广度优先  
  173.          /// <summary>  
  174.  /// 广度优先  
  175.  /// </summary>  
  176.  /// <param name="graph"></param>  
  177.          public void BFSTraverse(MatrixGraph graph)  
  178.          {  
  179.              //访问标记默认初始化  
  180.              for (int i = 0; i < graph.vertexNum; i++)  
  181.              {  
  182.                  graph.isTrav[i] = false;  
  183.              }  
  184.    
  185.              //遍历每个顶点  
  186.              for (int i = 0; i < graph.vertexNum; i++)  
  187.              {  
  188.                  //广度遍历未访问过的顶点  
  189.                  if (!graph.isTrav[i])  
  190.                  {  
  191.                      BFSM(ref graph, i);  
  192.                  }  
  193.              }  
  194.          }  
  195.    
  196.          /// <summary>  
  197.  /// 广度遍历具体算法  
  198.  /// </summary>  
  199.  /// <param name="graph"></param>  
  200.          public void BFSM(ref MatrixGraph graph, int vertex)  
  201.          {  
  202.              //这里就用系统的队列  
  203.              Queue<int> queue = new Queue<int>();  
  204.    
  205.              //先把顶点入队  
  206.              queue.Enqueue(vertex);  
  207.    
  208.              //标记此顶点已经被访问  
  209.              graph.isTrav[vertex] = true;  
  210.    
  211.              //输出顶点  
  212.              Console.Write(" ->" + graph.vertex[vertex]);  
  213.    
  214.              //广度遍历顶点的邻接点  
  215.              while (queue.Count != 0)  
  216.              {  
  217.                  var temp = queue.Dequeue();  
  218.    
  219.                  //遍历矩阵的横坐标  
  220.                  for (int i = 0; i < graph.vertexNum; i++)  
  221.                  {  
  222.                      if (!graph.isTrav[i] && graph.edges[temp, i] != 0)  
  223.                      {  
  224.                          graph.isTrav[i] = true;  
  225.    
  226.                          queue.Enqueue(i);  
  227.    
  228.                          //输出未被访问的顶点  
  229.                          Console.Write(" ->" + graph.vertex[i]);  
  230.                      }  
  231.                  }  
  232.              }  
  233.          }  
  234.          #endregion  
  235.   
  236.          #region 深度优先  
  237.          /// <summary>  
  238.  /// 深度优先  
  239.  /// </summary>  
  240.  /// <param name="graph"></param>  
  241.          public void DFSTraverse(MatrixGraph graph)  
  242.          {  
  243.              //访问标记默认初始化  
  244.              for (int i = 0; i < graph.vertexNum; i++)  
  245.              {  
  246.                  graph.isTrav[i] = false;  
  247.              }  
  248.    
  249.              //遍历每个顶点  
  250.              for (int i = 0; i < graph.vertexNum; i++)  
  251.              {  
  252.                  //广度遍历未访问过的顶点  
  253.                  if (!graph.isTrav[i])  
  254.                  {  
  255.                      DFSM(ref graph, i);  
  256.                  }  
  257.              }  
  258.          }  
  259.   
  260.          #region 深度递归的具体算法  
  261.          /// <summary>  
  262.  /// 深度递归的具体算法  
  263.  /// </summary>  
  264.  /// <param name="graph"></param>  
  265.  /// <param name="vertex"></param>  
  266.          public void DFSM(ref MatrixGraph graph, int vertex)  
  267.          {  
  268.              Console.Write("->" + graph.vertex[vertex]);  
  269.    
  270.              //标记为已访问  
  271.              graph.isTrav[vertex] = true;  
  272.    
  273.              //要遍历的六个点  
  274.              for (int i = 0; i < graph.vertexNum; i++)  
  275.              {  
  276.                  if (graph.isTrav[i] == false && graph.edges[vertex, i] != 0)  
  277.                  {  
  278.                      //深度递归  
  279.                      DFSM(ref graph, i);  
  280.                  }  
  281.              }  
  282.          }  
  283.          #endregion  
  284.          #endregion  
  285.   
  286.          #region prim算法获取最小生成树  
  287.          /// <summary>  
  288.  /// prim算法获取最小生成树  
  289.  /// </summary>  
  290.  /// <param name="graph"></param>  
  291.          public void Prim(MatrixGraph graph, out int sum)  
  292.          {  
  293.              //已访问过的标志  
  294.              int used = 0;  
  295.    
  296.              //非邻接顶点标志  
  297.              int noadj = -1;  
  298.    
  299.              //定义一个输出总权值的变量  
  300.              sum = 0;  
  301.    
  302.              //临时数组,用于保存邻接点的权值  
  303.              int[] weight = new int[graph.vertexNum];  
  304.    
  305.              //临时数组,用于保存顶点信息  
  306.              int[] tempvertex = new int[graph.vertexNum];  
  307.    
  308.              //取出邻接矩阵的第一行数据,也就是取出第一个顶点并将权和边信息保存于临时数据中  
  309.              for (int i = 1; i < graph.vertexNum; i++)  
  310.              {  
  311.                  //保存于邻接点之间的权值  
  312.                  weight[i] = graph.edges[0, i];  
  313.    
  314.                  //等于0则说明V1与该邻接点没有边  
  315.                  if (weight[i] == short.MaxValue)  
  316.                      tempvertex[i] = noadj;  
  317.                  else  
  318.                      tempvertex[i] = int.Parse(graph.vertex[0]);  
  319.              }  
  320.    
  321.              //从集合V中取出V1节点,只需要将此节点设置为已访问过,weight为0集合  
  322.              var index = tempvertex[0] = used;  
  323.              var min = weight[0] = short.MaxValue;  
  324.    
  325.              //在V的邻接点中找权值最小的节点  
  326.              for (int i = 1; i < graph.vertexNum; i++)  
  327.              {  
  328.                  index = i;  
  329.                  min = short.MaxValue;  
  330.    
  331.                  for (int j = 1; j < graph.vertexNum; j++)  
  332.                  {  
  333.                      //用于找出当前节点的邻接点中权值最小的未访问点  
  334.                      if (weight[j] < min && tempvertex[j] != 0)  
  335.                      {  
  336.                          min = weight[j];  
  337.                          index = j;  
  338.                      }  
  339.                  }  
  340.                  //累加权值  
  341.                  sum += min;  
  342.    
  343.                  Console.Write("({0},{1})  ", tempvertex[index], graph.vertex[index]);  
  344.    
  345.                  //将取得的最小节点标识为已访问  
  346.                  weight[index] = short.MaxValue;  
  347.                  tempvertex[index] = 0;  
  348.    
  349.                  //从最新的节点出发,将此节点的weight比较赋值  
  350.                  for (int j = 0; j < graph.vertexNum; j++)  
  351.                  {  
  352.                      //已当前节点为出发点,重新选择最小边  
  353.                      if (graph.edges[index, j] < weight[j] && tempvertex[j] != used)  
  354.                      {  
  355.                          weight[j] = graph.edges[index, j];  
  356.    
  357.                          //这里做的目的将较短的边覆盖点上一个节点的邻接点中的较长的边  
  358.                          tempvertex[j] = int.Parse(graph.vertex[index]);  
  359.                      }  
  360.                  }  
  361.              }  
  362.          }  
  363.          #endregion  
  364.   
  365.          #region dijkstra求出最短路径  
  366.          /// <summary>  
  367.  /// dijkstra求出最短路径  
  368.  /// </summary>  
  369.  /// <param name="g"></param>  
  370.          public void Dijkstra(MatrixGraph g)  
  371.          {  
  372.              int[] weight = new int[g.vertexNum];  
  373.    
  374.              int[] path = new int[g.vertexNum];  
  375.    
  376.              int[] tempvertex = new int[g.vertexNum];  
  377.    
  378.              Console.WriteLine("\n请输入源点的编号:");  
  379.    
  380.              //让用户输入要遍历的起始点  
  381.              int vertex = int.Parse(Console.ReadLine()) - 1;  
  382.    
  383.              for (int i = 0; i < g.vertexNum; i++)  
  384.              {  
  385.                  //初始赋权值  
  386.                  weight[i] = g.edges[vertex, i];  
  387.    
  388.                  if (weight[i] < short.MaxValue && weight[i] > 0)  
  389.                      path[i] = vertex;  
  390.    
  391.                  tempvertex[i] = 0;  
  392.              }  
  393.    
  394.              tempvertex[vertex] = 1;  
  395.              weight[vertex] = 0;  
  396.    
  397.              for (int i = 0; i < g.vertexNum; i++)  
  398.              {  
  399.                  int min = short.MaxValue;  
  400.    
  401.                  int index = vertex;  
  402.    
  403.                  for (int j = 0; j < g.vertexNum; j++)  
  404.                  {  
  405.                      //顶点的权值中找出最小的  
  406.                      if (tempvertex[j] == 0 && weight[j] < min)  
  407.                      {  
  408.                          min = weight[j];  
  409.                          index = j;  
  410.                      }  
  411.                  }  
  412.    
  413.                  tempvertex[index] = 1;  
  414.    
  415.                  //以当前的index作为中间点,找出最小的权值  
  416.                  for (int j = 0; j < g.vertexNum; j++)  
  417.                  {  
  418.                      if (tempvertex[j] == 0 && weight[index] + g.edges[index, j] < weight[j])  
  419.                      {  
  420.                          weight[j] = weight[index] + g.edges[index, j];  
  421.                          path[j] = index;  
  422.                      }  
  423.                  }  
  424.              }  
  425.    
  426.              Console.WriteLine("\n顶点{0}到各顶点的最短路径为:(终点 < 源点) " + g.vertex[vertex]);  
  427.    
  428.              //最后输出  
  429.              for (int i = 0; i < g.vertexNum; i++)  
  430.              {  
  431.                  if (tempvertex[i] == 1)  
  432.                  {  
  433.                      var index = i;  
  434.    
  435.                      while (index != vertex)  
  436.                      {  
  437.                          var j = index;  
  438.                          Console.Write("{0} < ", g.vertex[index]);  
  439.                          index = path[index];  
  440.                      }  
  441.                      Console.WriteLine("{0}\n", g.vertex[index]);  
  442.                  }  
  443.                  else  
  444.                  {  
  445.                      Console.WriteLine("{0} <- {1}: 无路径\n", g.vertex[i], g.vertex[vertex]);  
  446.                  }  
  447.              }  
  448.          }  
  449.          #endregion  
  450.      }  
  451.  }  


 

 

算法速成系列至此就全部结束了,公司给我们的算法培训也于上周五结束,呵呵,赶一下同步。最后希望大家能对算法重视起来,

学好算法,终身收益。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值