最小生成树,最短路径

prim最小生成树算法

 

1.任意选取一个起始顶点,并将它添加到最小生成树中。

2.将所有含起始顶点的边按照权重次序添加到minheap(最小堆)中。

3.从最小堆中取出最小边,并将这条边和那个新顶点添加到最小生成树中。

4.我们往minheap中添加所有含新顶点且另一顶点不在最小生成树中的

5.重复这一过程直到最小生成树含有原始图中的所有顶点时结束。

 

 

 

public Network mstNetwork()

   {

      int x, y;

      int index;

      double weight;

      int[] edge = new int[2];

      Heap<Double> minHeap = new Heap<Double>();

      Network<T> resultGraph = new Network<T>();

 

      if (isEmpty() || !isConnected())

         return resultGraph;

 

      resultGraph.adjMatrix = new double[numVertices][numVertices];

      for (int i = 0; i < numVertices; i++)

         for (int j = 0; j < numVertices; j++)

            resultGraph.adjMatrix[i][j] = Double.POSITIVE_INFINITY;

      resultGraph.vertices = (T[])(new Object[numVertices]);     

      

      boolean[] visited = new boolean[numVertices];

      for (int i = 0; i < numVertices; i++)

         visited[i] = false;

     

      edge[0] = 0;

      resultGraph.vertices[0] = this.vertices[0];

      resultGraph.numVertices++;

      visited[0] = true;

 

      /** Add all edges, which are adjacent to the starting vertex,

          to the heap */

      for (int i = 0; i < numVertices; i++)

            minHeap.addElement(new Double(adjMatrix[0][i]));

 

      while ((resultGraph.size() < this.size()) && !minHeap.isEmpty())

      {

         /** Get the edge with the smallest weight that has exactly

             one vertex already in the resultGraph */

         do

         {

            weight = (minHeap.removeMin()).doubleValue();

            edge = getEdgeWithWeightOf(weight, visited);

         } while (!indexIsValid(edge[0]) || !indexIsValid(edge[1]));

 

         x = edge[0];

         y = edge[1];

         if (!visited[x])

            index = x;

         else

            index = y;

 

         /** Add the new edge and vertex to the resultGraph */

         resultGraph.vertices[index] = this.vertices[index];

         visited[index] = true;

         resultGraph.numVertices++;

 

         resultGraph.adjMatrix[x][y] = this.adjMatrix[x][y];

         resultGraph.adjMatrix[y][x] = this.adjMatrix[y][x];

 

         /** Add all edges, that are adjacent to the newly added vertex,

             to the heap */

         for (int i = 0; i < numVertices; i++)

         {

            if (!visited[i] && (this.adjMatrix[i][index] <

                                Double.POSITIVE_INFINITY))

            {

               edge[0] = index;

               edge[1] = i;

               minHeap.addElement(new Double(adjMatrix[index][i]));

            }

         }

      }

      return resultGraph;

   }

 

最短路径:

 

A:两个顶点之间的最小边数

 

 

将广度优先遍历算法转变成寻找最短路径的算法

在遍历期间为每个顶点多存储两个信息

1.  从起始点到本顶点的路径长度,以及本顶点的前驱顶点

2.  起始顶点到本顶点的长度。

 

接着修改循环,使得当抵达目标顶点时循环终止,最短路径数就是从起始顶点到目标顶点前驱的路径长度再加1;如果要输出最短路径上的顶点,只需沿着前驱链回溯即可。

protected Iterator<Integer> iteratorShortestPathIndices

                              (int startIndex, int targetIndex)

   {

      int index = startIndex;

      int[] pathLength = new int[numVertices];

      int[] predecessor = new int[numVertices];

      LinkedQueue<Integer> traversalQueue = new LinkedQueue<Integer>();

      ArrayUnorderedList<Integer> resultList =

                                  new ArrayUnorderedList<Integer>();

 

      if (!indexIsValid(startIndex) || !indexIsValid(targetIndex) ||

                                       (startIndex == targetIndex))

         return resultList.iterator();

 

      boolean[] visited = new boolean[numVertices];

      for (int i = 0; i < numVertices; i++)

         visited[i] = false;

     

      traversalQueue.enqueue(new Integer(startIndex));

      visited[startIndex] = true;

      pathLength[startIndex] = 0;

      predecessor[startIndex] = -1;

 

      while (!traversalQueue.isEmpty() && (index != targetIndex))

      {

         index = (traversalQueue.dequeue()).intValue();

 

         /** Update the pathLength for each unvisited vertex adjacent

             to the vertex at the current index. */

         for (int i = 0; i < numVertices; i++)

         {

            if (adjMatrix[index][i] && !visited[i])

            {

               pathLength[i] = pathLength[index] + 1;

               predecessor[i] = index;

               traversalQueue.enqueue(new Integer(i));

               visited[i] = true;

            }

         }

      }

      if (index != targetIndex)  // no path must have been found

         return resultList.iterator();

 

      LinkedStack<Integer> stack = new LinkedStack<Integer>();

      index = targetIndex;

      stack.push(new Integer(index));

      do

      {

         index = predecessor[index];

         stack.push(new Integer(index));

      } while (index != startIndex);

     

      while (!stack.isEmpty())

         resultList.addToRear(((Integer)stack.pop()));

 

      return resultList.iterator();

   }

 

B:加权图的最小路径

使用一个minheap或优先队列来存储顶点,基于总权重(从起始顶点到本顶点的权重和)来衡量顶点对。这样我们总是能优先沿着最便宜的路径来游历图。

对每个顶点,都必须存储该顶点的标签,从起始顶点到本顶点的最便宜的路径的权重,路径上本顶点的前驱。在minheap中将存储顶点,对每条已经遇到但尚未游历的候选路径来权衡顶点对。从minheap取出顶点的时候,会权衡取自minheap的顶点对;如果遇到一个顶点的权重小于目前顶点中已存储的权重,则更新路径的代价。

 

protected Iterator<Integer> iteratorShortestPathIndices

                              (int startIndex, int targetIndex)

   {

      int index;

      double weight;

      int[] predecessor = new int[numVertices];

      Heap<Double> traversalMinHeap = new Heap<Double>();

      ArrayUnorderedList<Integer> resultList =

                                  new ArrayUnorderedList<Integer>();

      LinkedStack<Integer> stack = new LinkedStack<Integer>();

 

      int[] pathIndex = new int[numVertices];

      double[] pathWeight = new double[numVertices];

      for (int i = 0; i < numVertices; i++)

         pathWeight[i] = Double.POSITIVE_INFINITY;

 

      boolean[] visited = new boolean[numVertices];

      for (int i = 0; i < numVertices; i++)

         visited[i] = false;

 

      if (!indexIsValid(startIndex) || !indexIsValid(targetIndex) ||

                       (startIndex == targetIndex) || isEmpty())

         return resultList.iterator();

 

      pathWeight[startIndex] = 0;

      predecessor[startIndex] = -1;     

      visited[startIndex] = true;

      weight = 0;

 

      /** Update the pathWeight for each vertex except the

          startVertex. Notice that all vertices not adjacent

          to the startVertex  will have a pathWeight of

          infinity for now. */

      for (int i = 0; i < numVertices; i++)

      {

         if (!visited[i])

         {

            pathWeight[i] = pathWeight[startIndex] +

                            adjMatrix[startIndex][i];

            predecessor[i] = startIndex;

            traversalMinHeap.addElement(new Double(pathWeight[i]));

         }

      }

 

      do

      {

         weight = (traversalMinHeap.removeMin()).doubleValue();

         traversalMinHeap = new Heap<Double>();

         if (weight == Double.POSITIVE_INFINITY)  // no possible path

            return resultList.iterator();

         else

         {

            index = getIndexOfAdjVertexWithWeightOf(visited, pathWeight,

                                                    weight);

            visited[index] = true;

         }

 

         /** Update the pathWeight for each vertex that has has not been

             visited and is adjacent to the last vertex that was visited.

             Also, add each unvisited vertex to the heap. */

         for (int i = 0; i < numVertices; i++)

         {

            if (!visited[i])

            {

               if((adjMatrix[index][i] < Double.POSITIVE_INFINITY) &&

                  (pathWeight[index] + adjMatrix[index][i]) < pathWeight[i])

               {

                  pathWeight[i] = pathWeight[index] + adjMatrix[index][i];

                  predecessor[i] = index;

               }       

               traversalMinHeap.addElement(new Double(pathWeight[i]));

            }

         }

      } while (!traversalMinHeap.isEmpty() && !visited[targetIndex]);

 

      index = targetIndex;

      stack.push(new Integer(index));

      do

      {

         index = predecessor[index];

         stack.push(new Integer(index));

      } while (index != startIndex);

     

      while (!stack.isEmpty())

         resultList.addToRear((stack.pop()));

 

      return resultList.iterator();

   }

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值