図古典的なアルゴリズムダイクストラのアルゴリズム - データ構造(VI)

ダイクストラ法は、古典的なグラフアルゴリズムだけではありませんが、また、貪欲アルゴリズムのより良い例。

ダイクストラ法

開始点を指定する図VSにおけるダイクストラGによって最短パスを計算する際に(すなわち、頂点対から数えて)。

また、導入の2組のSとU-Sは、記録最短パス頂点を得られるという効果を有し、そしてUは、記録最短パスが決定され、頂点(頂点と対開始点までの距離)されていないです。

アルゴリズムステップ

(1)最初に、Sは対のみ開始点を含む; Uは「頂点までの距離対出発点」の頂点からの距離に対以外の頂点を含み、U [例えば、U頂点Vからは、対(ありますV)の長さ、及びVsとV]、V∞の距離に隣接していません。

(2)Uは「K頂点の最短距離」から選択され、Kは頂点Sに追加され、同時に、k個の頂点のUから除去されます。

(3)開始Vsに頂点からの距離の各々のUを更新します 理由Uの更新頂点距離、前のステップが他の頂点からKを使用して更新することができる最短パスk個の頂点を決定するために計算されるため、例えば、(対V)の距離よりも大きくてもよい(VSを、 K)+(K、V)の距離。

すべての頂点がトラバースされるまで(4)工程(2)及び(3)を繰り返します。

ここに画像を挿入説明

この例を置くために、本明細書の理解を容易にするために、使い捨てのコードを置くが、解体層、そして最後に要約しない例として、このコードに続きます

初期化データ

//初始化
boolean[] flag = new boolean[vertexes.length];	//用于判断是否已经被遍历的标示
int[] U = new int[vertexes.length];	//集合U,记录到各个点的距离
String[] S = new String[vertexes.length];	//集合S,已经计算完成的节点集合
int[] prev = new int[vertexes.length];	//用于记录路径的数组,just 记录而已

//vs表示起始节点的索引,初始化U为vs节点的所有边的权值,flag均为false
for (int i = 0; i < vertexes.length; i++) {
    flag[i] = false;
    U[i] = matrix[vs][i];
    prev[i] = 0;
}

処理開始ノード

//起始节点的处理
S[0] = vertexes[vs]; //起始节点进入S集合
flag[vs] = true;	//标记起始节点为已访问
U[vs] = 0;	//将U集合中,vs的权值置为0,毕竟从自己到自己权值为0;

全体的なフレームワークのコアダイクストラ

for (int i = 0; i < vertexes.length; i++) {
	//1、找到当前U中最小的元素,并记录下该元素的下标(编程入门难度的逻辑)
    
    //2、将第一步找到的节点加入集合S,并将其标记为已经访问
    
    //3、更新集合U
}

実際には、構造が完了した後に、これらのステップは、最も困難が第三段階であるようで、安心して、実際には、それは難しいことではありません、ここで直接バーコードの第三段階を掲載

int k = 0;
for (int i = 0; i < vertexes.length; i++) {
    //先找到当前U中最小的节点,并记录下标
    int min = MAX_WEIGHT;
    for (int j = 0; j < vertexes.length; j++) {
        if (U[j] < min && flag[j] == false) {
            min = U[j];
            k = j;
        }
    }

    //找到的节点应该入S集合
    S[i] = vertexes[k];
    flag[k] = true;//同时标记该最小值的节点为被访问。

    //继续更新集合U
    for (int j = 0; j < vertexes.length; j++) {
        //temp记录为当前的min+当前节点到其他可达节点的权值。
        //int temp = min + matrix[k][j];//直接这么写会产生位溢出,毕竟用到了Integer.MAX_VALUE
        int temp = matrix[k][j] == MAX_WEIGHT ? MAX_WEIGHT : (min + matrix[k][j]);

        //正式开始更新U集合
        if (flag[j] == false && temp < U[j]) {
            U[j] = temp;
            prev[j] = k; //记录一下节点前驱下标。
        }
    }
}

印刷パス

//开始打印路径
System.out.println("起始顶点:" + vertexes[vs]);
for (int i = 0; i < vertexes.length; i++) {
    System.out.print("最短路径(" + vertexes[vs] + "," + vertexes[i] + "):" + U[i] + "  ");

    List<String> path = new ArrayList<>();
    int j = i;
    while (true) {
        path.add(vertexes[j]);
        if (j == 0) {
            break;
        }
        j = prev[j];
    }

    //完成打印工作
    for (int x = path.size() - 1; x >= 0; x--) {
        if (x == 0) {
            System.out.println(path.get(x));
        } else {
            System.out.print(path.get(x) + "->");
        }
    }
}

ロジックは、配列の添字によってだけではなく、ここで、印刷、および同じチェーンを取ることは難しいことではありません。ここでは説明されていない、非常に簡単です。

完全なコード

プラステストコードは、すべて一緒に、直接実行することができます

import com.learn.graph.MatrixNDG;
import java.util.ArrayList;
import java.util.List;

/**
 * autor:liman
 * createtime:2020/2/14
 * comment:迪杰斯特拉算法
 */
public class ShorestPathDijkstraSelf {

    private int[][] matrix;

    private int MAX_WEIGHT = Integer.MAX_VALUE;

    private String[] vertexes;

    /**
     * 构建图
     *
     * @param index
     */
    public void createGraph(int index) {
        matrix = new int[index][index];
        vertexes = new String[index];

        int[] v0 = {0, 1, 5, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT};
        int[] v1 = {1, 0, 3, 7, 5, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT};
        int[] v2 = {5, 3, 0, MAX_WEIGHT, 1, 7, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT};
        int[] v3 = {MAX_WEIGHT, 7, MAX_WEIGHT, 0, 2, MAX_WEIGHT, 3, MAX_WEIGHT, MAX_WEIGHT};
        int[] v4 = {MAX_WEIGHT, 5, 1, 2, 0, 3, 6, 9, MAX_WEIGHT};
        int[] v5 = {MAX_WEIGHT, MAX_WEIGHT, 7, MAX_WEIGHT, 3, 0, MAX_WEIGHT, 5, MAX_WEIGHT};
        int[] v6 = {MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 3, 6, MAX_WEIGHT, 0, 2, 7};
        int[] v7 = {MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 9, 5, 2, 0, 4};
        int[] v8 = {MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 7, 4, 0};

        matrix[0] = v0;
        matrix[1] = v1;
        matrix[2] = v2;
        matrix[3] = v3;
        matrix[4] = v4;
        matrix[5] = v5;
        matrix[6] = v6;
        matrix[7] = v7;
        matrix[8] = v8;

        vertexes[0] = "v0";
        vertexes[1] = "v1";
        vertexes[2] = "v2";
        vertexes[3] = "v3";
        vertexes[4] = "v4";
        vertexes[5] = "v5";
        vertexes[6] = "v6";
        vertexes[7] = "v7";
        vertexes[8] = "v8";
    }

    public void dijkstra(int vs) {
        //初始化
        boolean[] flag = new boolean[vertexes.length];
        int[] U = new int[vertexes.length];
        String[] S = new String[vertexes.length];
        int[] prev = new int[vertexes.length];

        for (int i = 0; i < vertexes.length; i++) {
            flag[i] = false;
            U[i] = matrix[vs][i];
            prev[i] = 0;
        }

        //起始节点的处理
        S[0] = vertexes[vs];
        flag[vs] = true;
        U[vs] = 0;

        int k = 0;
        for (int i = 0; i < vertexes.length; i++) {
            //先找到当前U中最小的节点,并记录下标
            int min = MAX_WEIGHT;
            for (int j = 0; j < vertexes.length; j++) {
                if (U[j] < min && flag[j] == false) {
                    min = U[j];
                    k = j;
                }
            }

            //找到的节点应该入S集合
            S[i] = vertexes[k];
            flag[k] = true;//同时标记该最小值的节点为被访问。

            //继续更新集合U
            for (int j = 0; j < vertexes.length; j++) {
//                int temp = min + matrix[k][j];//直接这么写会产生位溢出,毕竟用到了MAX_VALUE
                int temp = matrix[k][j] == MAX_WEIGHT ? MAX_WEIGHT : (min + matrix[k][j]);

                //正式开始更新U集合
                if (flag[j] == false && temp < U[j]) {
                    U[j] = temp;
                    prev[j] = k;
                }
            }
        }

        //开始打印路径
        System.out.println("起始顶点:" + vertexes[vs]);
        for (int i = 0; i < vertexes.length; i++) {
            System.out.print("最短路径(" + vertexes[vs] + "," + vertexes[i] + "):" + U[i] + "  ");

            List<String> path = new ArrayList<>();
            int j = i;
            while (true) {
                path.add(vertexes[j]);
                if (j == 0) {
                    break;
                }
                j = prev[j];
            }

            //完成打印工作
            for (int x = path.size() - 1; x >= 0; x--) {
                if (x == 0) {
                    System.out.println(path.get(x));
                } else {
                    System.out.print(path.get(x) + "->");
                }
            }
        }

        //打印一遍S集合
        System.out.println("顶点放入到S中的顺序");
        for (int i = 0; i < vertexes.length; i++) {
            System.out.print(S[i]);
            if (i != vertexes.length - 1) {
                System.out.print("-->");
            }
        }

    }

    public static void main(String[] args) {
        ShorestPathDijkstraSelf shorestPathDijkstra = new ShorestPathDijkstraSelf();
        shorestPathDijkstra.createGraph(9);
        shorestPathDijkstra.dijkstra(0);
    }

}

結果:
ここに画像を挿入説明

概要

難しいですか?一見それほど困難。貪欲アルゴリズムの古典的な例

公開された133元の記事 ウォン称賛37 ビュー90000 +

おすすめ

転載: blog.csdn.net/liman65727/article/details/104334030
おすすめ