最短路徑(圖中兩點間最短路徑)


求解城市之間的最短距離是一個非常實際的問題,其大意如下:

某地區由n個城市,如何選擇路線使某個城市到某個指定城市的的距離最短?

注意:這里需要求解的最短路徑指的是兩個城市之間的最短距離,而不是所有城市之間最短總距離。

1.最短路徑算法

    //最短路徑算法
    static void distMin(GraphMatrix GM,int vend){    //vend為結束點
        int[] weight=new int[GraphMatrix.MaxNum];        //某終止點到各頂點的最短路徑長度
        int i,j,k,min;
        vend--;
        for(i=0;i<GM.VertexNum;i++){        //初始化weight數組
            weight[i]=GM.EdgeWeight[vend][i];
        }
        for(i=0;i<GM.VertexNum;i++){        //初始化path數組
            if(weight[i]<MaxValue&&weight[i]>0){    //有效權值
                path[i]=vend;
            }
        }
        for(i=0;i<GM.VertexNum;i++){        //初始化tmpvertex數組
            tmpvertex[i]=0;            //初始化頂點集合為空
        }
        tmpvertex[vend]=1;        //選入頂點vend
        weight[vend]=0;
        for(i=0;i<GM.VertexNum;i++){        //查找未用頂點的最小權值
            min=MaxValue;
            k=vend;
            for(j=0;j<GM.VertexNum;j++){
                if(tmpvertex[j]==0&&weight[j]<min){
                    min=weight[j];
                    k=j;
                }
            }
            tmpvertex[k]=1;            //將頂點k選入
            for(j=0;j<GM.VertexNum;j++){        //以頂點k為中間點,重新計算權值
                if(tmpvertex[j]==0&&weight[k]+GM.EdgeWeight[k][j]<weight[j]){
                    weight[j]=weight[k]+GM.EdgeWeight[k][j];
                    path[j]=k;
                }
            }
        }
    }

2.完整的程序代碼示例

package com.cn.datastruct;

import java.util.Scanner;

//最短路徑求解
public class DistMin {
    static class GraphMatrix{
        static final int MaxNum=20;
        char[] Vertex=new char[MaxNum];  //保存頂點信息(序號或字母)
        int GType;    //圖的類型(0:無向圖,1:有向圖)
        int VertexNum;        //頂點的數量
        int EdgeNum;        //邊的數量
        int[][] EdgeWeight=new int[MaxNum][MaxNum];        //保存邊的權
        int[] isTrav=new int[MaxNum];        //遍歷標志
    }
    
    static final int MaxValue=65535;    //最大值(可設為一個最大整數)
    static int[] path=new int[GraphMatrix.MaxNum];    //兩點經過的頂點集合的數組
    static int[] tmpvertex=new int[GraphMatrix.MaxNum];  //最短路徑的起始點集合
    static Scanner input=new Scanner(System.in);
    
    //創建鄰接矩陣圖
    static void CreateGraph(GraphMatrix GM){
        int i,j,k;
        int weight;     //
        char EstartV,EendV;        //邊的起始頂點
        System.out.printf("輸入圖中各頂點信息\n");
        for(i=0;i<GM.VertexNum;i++){        //輸入頂點
            System.out.printf("第%d個頂點:", i+1);
            GM.Vertex[i]=(input.next().toCharArray())[0];  //保存到各頂點的數組元素中
        }
        System.out.printf("輸入構成各邊的頂點及權值:\n");
        for(k=0;k<GM.EdgeNum;k++){            //輸入邊的信息
            System.out.printf("第%d條邊:", k+1);
            EstartV=input.next().charAt(0);
            EendV=input.next().charAt(0);
            weight=input.nextInt();
            for(i=0;EstartV!=GM.Vertex[i];i++);      //在已有頂點中查找始點
            for(j=0;EendV!=GM.Vertex[j];j++);        //在已有的頂點中查找終點
            GM.EdgeWeight[i][j]=weight;          //對應位置保存權值,表示有一條邊
            if(GM.GType==0){        //若是無向圖
                GM.EdgeWeight[j][i]=weight;        //在對角位置保存權值
            }
        }
    }

    // 清空矩陣
    static void ClearGraph(GraphMatrix GM) {
        int i, j;
        for (i = 0; i < GM.VertexNum; i++) {
            for (j = 0; j < GM.VertexNum; j++) {
                GM.EdgeWeight[i][j] = MaxValue; // 設置矩陣中各元素的值為MaxValue
            }
        }
    }

    // 輸出鄰接矩陣
    static void OutGraph(GraphMatrix GM) {
        int i, j;
        for (j = 0; j < GM.VertexNum; j++) {
            System.out.printf("\t%c", GM.Vertex[j]); // 在第一行輸出頂點信息
        }
        System.out.println();
        for (i = 0; i < GM.VertexNum; i++) {
            System.out.printf("%c", GM.Vertex[i]);
            for (j = 0; j < GM.VertexNum; j++) {
                if (GM.EdgeWeight[i][j] == MaxValue) { // 若權值為最大值
                    System.out.printf("\tZ"); // 以Z表示無窮大
                } else {
                    System.out.printf("\t%d", GM.EdgeWeight[i][j]); // 輸出邊的權值
                }
            }
            System.out.println();
        }
    }
    
    //最短路徑算法
    static void distMin(GraphMatrix GM,int vend){    //vend為結束點
        int[] weight=new int[GraphMatrix.MaxNum];        //某終止點到各頂點的最短路徑長度
        int i,j,k,min;
        vend--;
        for(i=0;i<GM.VertexNum;i++){        //初始化weight數組
            weight[i]=GM.EdgeWeight[vend][i];
        }
        for(i=0;i<GM.VertexNum;i++){        //初始化path數組
            if(weight[i]<MaxValue&&weight[i]>0){    //有效權值
                path[i]=vend;
            }
        }
        for(i=0;i<GM.VertexNum;i++){        //初始化tmpvertex數組
            tmpvertex[i]=0;            //初始化頂點集合為空
        }
        tmpvertex[vend]=1;        //選入頂點vend
        weight[vend]=0;
        for(i=0;i<GM.VertexNum;i++){        //查找未用頂點的最小權值
            min=MaxValue;
            k=vend;
            for(j=0;j<GM.VertexNum;j++){
                if(tmpvertex[j]==0&&weight[j]<min){
                    min=weight[j];
                    k=j;
                }
            }
            tmpvertex[k]=1;            //將頂點k選入
            for(j=0;j<GM.VertexNum;j++){        //以頂點k為中間點,重新計算權值
                if(tmpvertex[j]==0&&weight[k]+GM.EdgeWeight[k][j]<weight[j]){
                    weight[j]=weight[k]+GM.EdgeWeight[k][j];
                    path[j]=k;
                }
            }
        }
    }
    
    public static void main(String[] args) {
        GraphMatrix GM=new GraphMatrix();   //定義保存鄰接表結構的圖
        String go;
        int vend;
        int i,k;
        System.out.println("求解最短路徑問題!");
        do{
            System.out.print("請先輸入生成圖的類型:");
            GM.GType=input.nextInt();   //圖的種類
            System.out.print("請輸入圖的頂點數量:");
            GM.VertexNum=input.nextInt();         //輸入圖中頂點數
            System.out.print("請輸入圖的邊的數量:");
            GM.EdgeNum=input.nextInt();        //輸入圖中邊數
            ClearGraph(GM);            //清空圖
            CreateGraph(GM);        //生成鄰接表結構的圖
            
            System.out.print("\n請輸入結束點:");
            vend=input.nextInt();
            
            distMin(GM,vend);
            vend--;
            System.out.printf("\n個頂點到達頂點%c的最短路徑分別為(起始點-結束點):\n",GM.Vertex[vend]);
            for(i=0;i<GM.VertexNum;i++){        //輸出結果
                if(tmpvertex[i]==1){
                    k=i;
                    while(k!=vend){
                        System.out.printf("頂點%c-", GM.Vertex[k]);
                        k=path[k];
                    }
                    System.out.printf("頂點%c\n", GM.Vertex[k]);
                }else{
                    System.out.printf("%c-%c:無路徑\n", GM.Vertex[i],GM.Vertex[vend]);
                }
            }
            System.out.println("\n繼續玩嗎(y/n)?");
            go=input.next();
        }while(go.equalsIgnoreCase("y"));
        System.out.println("游戲結束!");
    }

}

程序運行結果如下:

求解最短路徑問題!
請先輸入生成圖的類型:0
請輸入圖的頂點數量:5
請輸入圖的邊的數量:6
輸入圖中各頂點信息
第1個頂點:1
第2個頂點:2
第3個頂點:3
第4個頂點:4
第5個頂點:5
輸入構成各邊的頂點及權值:
第1條邊:1 2 2
第2條邊:1 3 5
第3條邊:1 5 3
第4條邊:2 4 4
第5條邊:3 5 5
第6條邊:4 5 2

請輸入結束點:1

個頂點到達頂點1的最短路徑分別為(起始點-結束點):
頂點1
頂點2-頂點1
頂點3-頂點1
頂點4-頂點5-頂點1
頂點5-頂點1

繼續玩嗎(y/n)?
n
游戲結束!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM