单源最短路径Dijkstra,C++\Java

来源:互联网 发布:linux sed命令 编辑:程序博客网 时间:2024/05/20 02:27

简述

该算法只简单演示Dijkstra求最短路径值,二维数组G[][]存储顶点及权值信息,顶点集合为V={1,2,3,…,N},源点为1,集合P用于存储每次选取的最小顶点,一位数组dis[j]用于存储源点1到各顶点j的最短路径值,算法核心思想及步骤

  • 初始集合P为空,加入源点1;初始dis[]为源点1到其他各点的权值
  • 集合P != V,选取源点1到集合V-P最近的顶点k,加入P
  • 对以k发出的边进行松弛,重新更新整合dis[]
  • 重复直到集合P = V

等以后再把算法正确性的证明给出


代码C++

此算法没有给出路径输出,路径输出只需要在第三步松弛操作加一个一位数组记录每个结点最短路径的前一个点就行。

#include <iostream>#include <vector>using namespace std;int main(int argc, const char * argv[]) {    const int M = 10000;    const int N = 6;//顶点为1,2,...N,为集合V    int G[][N+1] = {//图的信息,边和权值        {0,0,0,0,0,0,0},        {0,0,4,M,2,M,M},        {0,1,0,4,M,M,M},        {0,M,4,0,M,M,7},        {0,2,M,M,0,5,M},        {0,M,M,M,5,0,6},        {0,M,M,7,M,6,0},    };    int dis[N+1];//源点1到其他各定点的最短路径值    dis[1] = 0;//点1到点1的距离    int visit[N+1];//记录集合P访问的点    visit[1] = 1;    for(int j=2; j <= N; j++) {//给路径值初始化,初始估计值为点1到其他点的权值        if(G[1][j] != M) {            dis[j] = G[1][j];        }        else            dis[j] = M;        visit[j] = 0;    }    vector<int> P;//集合P用于存储选取的顶点,剩余顶点集合为V-P    P.push_back(1);    while (P.size() != N) {//算法以所有顶点都在集合P中,结束        //第一步,选取集合V-P里距离集合P最近的顶点k        int min = M;        int k = 0;        for(int j = 1; j <= N; j++) {            if( visit[j] == 0 && dis[j] < min) {                min = dis[j];                k = j;            }        }        //第二步,将顶点k加入集合P        P.push_back(k);        visit[k] = 1;        //第三步,松弛以顶点k发出的边,即对源点1到其他各顶点i的距离dis[j]与源点1到顶点k的距离dis[k] + k到j权值之和进行比较        for(int j = 1; j <= N; j++) {            if(dis[j] > dis[k] + G[k][j])                dis[j] = dis[k] + G[k][j];        }    }    for(int i = 1; i <= N; i++) {        cout << i << "\t";    }    cout << endl;    for(int i = 1; i <= N; i++) {        cout << dis[i] << "\t";    }    cout << endl;    return 0;}

代码Java

这个给出了路径输出,更全面点

import java.util.ArrayList;import java.util.List;public class Dijkstra {    public static void main(String[] args) {        int M = 10000;        int N = 6;        int[][] G = { // 图的信息,边和权值            {0,0,0,0,0,0,0},            {0,0,4,M,2,M,1},            {0,1,0,4,M,M,M},            {0,M,4,0,M,M,7},            {0,2,M,M,0,5,M},            {0,M,M,M,5,0,6},            {0,1,M,7,M,6,0},         };        int[] dis = new int[N + 1];// 最短路径值        for (int j = 1; j <= N; j++) {            dis[j] = G[1][j];        }        int[] pre = new int[N + 1];// 存取前缀        List<Integer> list = new ArrayList<Integer>();        list.add(1);        while (list.size() < N) {            // 第一步,选取集合V-P里距离集合P最近的顶点k            int min = M;            int k = 0;            for (int j = 1; j <= N; j++) {                if (!list.contains(j) && dis[j] < min) {                    min = dis[j];                    k = j;                }            }            // 第二步,将顶点k加入集合P            list.add(k);            // 第三步,松弛以顶点k发出的边,即对源点1到其他各顶点i的距离dis[j]与源点1到顶点k的距离dis[k] +            // k到j权值之和进行比较            for (int j = 1; j <= N; j++) {                if (dis[j] > dis[k] + G[k][j]) {                    dis[j] = dis[k] + G[k][j];                    pre[j] = k;// 就是把每个结点之前的结点位置如pre[6] = 5,说明最短路径第6结点前面是第5结点                }            }        }        // 以下为遍历结果,不是算法的核心        for (int j = 1; j <= N; j++) {            List<Integer> pathlist = new ArrayList<Integer>();            if (pre[j] == 0) {                pathlist.add(j);            } else {                int p = j;                while (pathlist.add(p) && pre[p] != 0) {                    p = pre[p];                }            }            pathlist.add(1);            System.out.print("1->" + j + "的最短路径为:");            for (int i = 0; i < pathlist.size(); i++) {                System.out.print(pathlist.get(pathlist.size() - 1 - i) + " ");            }            System.out.println(", 路径长:" + dis[j]);        }    }}

java版输出结果截图:
这里写图片描述

原创粉丝点击