贪心算法-单源最短路径

给定带权有向图G =(V,E),其中每条边的权是非负实数。另外,还给定V中的一个顶点,称为源。现在要计算从源到所有其它各顶点的最短路长度。这里路的长度是指路上各边权之和。这个问题通常称为单源最短路径问题。

Dijkstra算法是解单源最短路径问题的贪心算法。其基本思想是,设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。

初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度。Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,同时对数组dist作必要的修改。一旦S包含了所有V中顶点,dist就记录了从源到所有其它顶点之间的最短路径长度。

例如,对下图中的有向图,应用Dijkstra算法计算从源顶点1到其它顶点间最短路径的过程列在下表中。

Dijkstra算法的迭代过程:

7JPLG7ZB@_J360{`(X@N1TE

具体代码实现:

   1: import java.util.Stack;
   2:  
   3: public class Dijkstra {
   4:     static int MAX_SIZE = 6;
   5:     public static void dijkstra(int startVertex, float[][] weight,
   6:             float[] minDist, int[] prev, int[][] path) {
   7:         int n = minDist.length - 1;
   8:         if (startVertex < 1 || startVertex > n)
   9:             return;
  10:         boolean[] s = new boolean[n + 1]; //是否将蓝点集加入红点集的标志
  11:  
  12:         // startVertex为顶点1
  13:         minDist[startVertex] = 0; //初始红点集
  14:         s[startVertex] = true;
  15:         for (int i = 2; i <= n; i++) {
  16:             minDist[i] = weight[startVertex][i]; //设置初始距离为weight<s,i>
  17:             s[i] = false;
  18:             if (minDist[i] == Float.MAX_VALUE) {
  19:                 prev[i] = 0;
  20:                 path[i][startVertex] = 0;
  21:             } else {
  22:                 prev[i] = startVertex;
  23:                 path[i][startVertex] = 1;
  24:             }
  25:         }
  26:         // 扩充红点集
  27:         for (int i = 1; i < n; i++) {
  28:             float temp = Float.MAX_VALUE;
  29:             int u = startVertex;
  30:             // 在当前蓝点集中选估计距离最小的顶点j
  31:             for (int j = 2; j <= n; j++) {
  32:                 if ((!s[j]) && (minDist[j] < temp)) {
  33:                     u = j;//k是V集合中具有最短“特殊路径的顶点”,所谓特殊路径即是从顶点v到k只经过U中的顶点  
  34:                     temp = minDist[j];
  35:                 }
  36:             }
  37:  
  38:             // 如果仍为无穷大,则说明为不连通图
  39:             if (Float.MAX_VALUE == temp)
  40:                 return;
  41:  
  42:             s[u] = true; // 将蓝点集u扩充到红点集
  43:             // 调整源点s与剩余蓝点之间的距离
  44:             for (int j = 2; j <= n; j++)
  45:                 if ((!s[j]) && (weight[u][j] < Float.MAX_VALUE)) {
  46:                     float newDist = minDist[u] + weight[u][j];
  47:                     if (newDist < minDist[j]) {
  48:                         minDist[j] = newDist;
  49:                         prev[j] = u;
  50:  
  51:                         path[j][startVertex] = u;
  52:                     }
  53:                 }
  54:         }        
  55:     }
  56:  
  57:     public static void main(String args[]) {
  58:         float weight[][] = new float[MAX_SIZE][MAX_SIZE];//边权
  59:         float[] minDist = new float[MAX_SIZE]; //源点到其它顶点的最短距离数组
  60:         int[] prev = new int[MAX_SIZE]; // s到t经过顶点的集合
  61:         int[][] path = new int[MAX_SIZE][MAX_SIZE];
  62:         for (int i = 0; i < MAX_SIZE; i++)
  63:             for (int j = 0; j < MAX_SIZE; j++)
  64:                 weight[i][j] = Float.MAX_VALUE;
  65:         for (int i = 0; i < MAX_SIZE; i++)
  66:             for (int j = 0; j < MAX_SIZE; j++)
  67:                 path[i][j] = 0;
  68:         weight[1][2] = 10;
  69:         weight[1][4] = 30;
  70:         weight[1][5] = 100;
  71:         weight[2][3] = 50;
  72:         weight[3][5] = 10;
  73:         weight[4][3] = 20;
  74:         weight[4][5] = 60;
  75:         int startVertex = 1;// 假设从顶点1处出发
  76:  
  77:         dijkstra(startVertex, weight, minDist, prev, path);
  78:         System.out.println("从1出发到2、3、4、5的最短路径依次是:");
  79:         for (int j = 2; j < MAX_SIZE; j++) {
  80:             System.out.println(minDist[j]);
  81:         }
  82:         System.out.println("path矩阵如下:");
  83:         for (int i = 0; i < MAX_SIZE; i++) {
  84:             for (int j = 0; j < MAX_SIZE; j++) {
  85:                 System.out.print(path[i][j] + " ");
  86:             }
  87:             System.out.println();
  88:         }
  89:         System.out.println("从1到5最短路径经过的点为:");        
  90:         int endVertex = 5;
  91:         Stack<Integer> stack = new Stack<Integer>();
  92:         System.out.print(startVertex+" ");
  93:         printPath(path, startVertex, endVertex,stack);
  94:         
  95:     }
  96:  
  97:     // 栈处理
  98:     static void printPath(int[][] path, int startVertex, int endVertex,Stack<Integer> pathStack) {
  99:         if (path[endVertex][startVertex] != 0)//&&path[endVertex][startVertex]!=startVertex
 100:         {
 101:             pathStack.push(endVertex);
 102:             int temp = path[endVertex][startVertex];
 103:             printPath(path, startVertex, temp,pathStack);    
 104:             System.out.print(pathStack.pop() + " ");
 105:         }        
 106:     }
 107: }

转载于:https://www.cnblogs.com/ttltry-air/archive/2012/07/31/2617121.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值