Java での最短パス アルゴリズムのためのダイクストラ アルゴリズムの実装
この記事では、Javaで最短経路アルゴリズムを実装するダイクストラアルゴリズムを中心に紹介します。ダイクストラアルゴリズムは、シングルスタートフルパスアルゴリズムです。興味のある方は学習してください。
はじめに ダイクストラのアルゴリズムはよく知られた最短経路アルゴリズムであり、シングルスタートフルパスアルゴリズムです。このアルゴリズムは「貪欲アルゴリズム」の成功例と呼ばれています。この記事では、この優れたアルゴリズムを最も一般的な言語で紹介し、Java 実装コードを提供します。
1. 知識の準備:
1. グラフを表すデータ構造このアルゴリズムでは、著者は隣接行列を使用します。
グラフの隣接行列の保存方法は、2 つの配列を使用してグラフを表現することです。 1 次元配列にはグラフの頂点情報が格納され、2 次元配列 (隣接行列) にはグラフのエッジまたは円弧の情報が格納されます。
グラフ G に n 個の頂点があると仮定すると、隣接行列は次のように定義される n*n 正方行列になります。
上記からわかるように、無向グラフのエッジ配列は対称行列です。いわゆる対称行列とは、n 次行列の要素が aij = aji を満たすことを意味します。つまり、行列の左上隅から右下隅までの主対角線が軸となり、右上隅の要素と左下隅の対応する要素はすべて等しいということです。
このマトリックスから、画像内の情報を簡単に知ることができます。
(1) 2 つの頂点にエッジがあるかないかを判断するのは非常に簡単です。
(2) 特定の頂点の次数を知るには、実際には頂点 vi が i 番目の行にあるか、または隣接行列の (i 番目の列) 頂点 vi の要素と出力次数の合計、頂点 vi の入次数は 1 であり、これはまさに i 番目の列の数値の合計です。頂点 vi の出次数は 2 で、これは i 番目の行の数値の合計です。
有向グラフの定義も同様なので詳細は割愛します。
2. 単一開始点フルパスいわゆる単一開始点フルパスとは、グラフ内の開始点からすべてのノードまでの最短パスを指します。
3. グラフ理論の基礎知識 (読者は関連する情報を自分で見つける必要があります)
4. 相補緩和条件
スカラー d1、d2、....、dN が
dj に属し、P は i1 を始点、ik を終点とする道路です。 dj = di + aij の場合、すべての辺 (i, j) P の場合、P これは、i1 から ik への最短経路です。このうち、上の 2 つの式を満たす最短経路問題の相補緩和条件と呼ばれます。 2. アルゴリズムのアイデア 1. G = (V, E) を重み付き無向グラフとする。 G に 2 つの隣接するノードがある場合、i と j。 aij (ここでは添字で表現します。以降注意してください) はノード i からノード j までの重みであり、このアルゴリズムでは距離として理解できます。各ノードには、開始点からそこへの特定のパスまでの距離を示す値 di (ノード ラベル) があります。 2. アルゴリズムには最初、未訪問のノードのリストを保存するために使用される配列 V があり、これを一時的に候補リストと呼びます。開始ノードとしてノード 1 を選択します。初めに、ノード 1 では d1=0、他のノードでは di=無限大、V はすべてのノードです。条件を初期化した後、反復アルゴリズムを開始し、V が空集合になったときに停止します。具体的な反復手順は次のとおりです。 d 値が最小のノード di を候補リストから削除します。 (この例では、V のデータ構造は優先キューを使用して最小値デキューを実装しています。以前の記事で紹介したフィボナッチ ペアを使用するのが最適で、パフォーマンスが大幅に向上します)。このノードから始まる各エッジについて、V が削除されたノードを除き、(i, j) は A に属します。 dj > di + aij (緩和条件に違反) の場合、 dj = di + aij , ( j が V から削除されている場合は、その最小距離が計算されており、この計算には参加しないことを意味します)
アルゴリズムの計算工学では、ノードの d 値が単調に増加しないことがわかります
具体的なアルゴリズム 図は以下の通り
public class Vertex implements Comparable<Vertex>{ /** * 节点名称(A,B,C,D) */ private String name; /** * 最短路径长度 */ private int path; /** * 节点是否已经出列(是否已经处理完毕) */ private boolean isMarked; public Vertex(String name){ this.name = name; this.path = Integer.MAX_VALUE; //初始设置为无穷大 this.setMarked(false); } public Vertex(String name, int path){ this.name = name; this.path = path; this.setMarked(false); } @Override public int compareTo(Vertex o) { return o.path > path?-1:1; } }
public class Graph {
/*
* 顶点
*/
private List<Vertex> vertexs;
/*
* 边
*/
private int[][] edges;
/*
* 没有访问的顶点
*/
private Queue<Vertex> unVisited;
public Graph(List<Vertex> vertexs, int[][] edges) {
this.vertexs = vertexs;
this.edges = edges;
initUnVisited();
}
/*
* 搜索各顶点最短路径
*/
public void search(){
while(!unVisited.isEmpty()){
Vertex vertex = unVisited.element();
//顶点已经计算出最短路径,设置为"已访问"
vertex.setMarked(true);
//获取所有"未访问"的邻居
List<Vertex> neighbors = getNeighbors(vertex);
//更新邻居的最短路径
updatesDistance(vertex, neighbors);
pop();
}
System.out.println("search over");
}
/*
* 更新所有邻居的最短路径
*/
private void updatesDistance(Vertex vertex, List<Vertex> neighbors){
for(Vertex neighbor: neighbors){
updateDistance(vertex, neighbor);
}
}
/*
* 更新邻居的最短路径
*/
private void updateDistance(Vertex vertex, Vertex neighbor){
int distance = getDistance(vertex, neighbor) + vertex.getPath();
if(distance < neighbor.getPath()){
neighbor.setPath(distance);
}
}
/*
* 初始化未访问顶点集合
*/
private void initUnVisited() {
unVisited = new PriorityQueue<Vertex>();
for (Vertex v : vertexs) {
unVisited.add(v);
}
}
/*
* 从未访问顶点集合中删除已找到最短路径的节点
*/
private void pop() {
unVisited.poll();
}
/*
* 获取顶点到目标顶点的距离
*/
private int getDistance(Vertex source, Vertex destination) {
int sourceIndex = vertexs.indexOf(source);
int destIndex = vertexs.indexOf(destination);
return edges[sourceIndex][destIndex];
}
/*
* 获取顶点所有(未访问的)邻居
*/
private List<Vertex> getNeighbors(Vertex v) {
List<Vertex> neighbors = new ArrayList<Vertex>();
int position = vertexs.indexOf(v);
Vertex neighbor = null;
int distance;
for (int i = 0; i < vertexs.size(); i++) {
if (i == position) {
//顶点本身,跳过
continue;
}
distance = edges[position][i]; //到所有顶点的距离
if (distance < Integer.MAX_VALUE) {
//是邻居(有路径可达)
neighbor = getVertex(i);
if (!neighbor.isMarked()) {
//如果邻居没有访问过,则加入list;
neighbors.add(neighbor);
}
}
}
return neighbors;
}
/*
* 根据顶点位置获取顶点
*/
private Vertex getVertex(int index) {
return vertexs.get(index);
}
/*
* 打印图
*/
public void printGraph() {
int verNums = vertexs.size();
for (int row = 0; row < verNums; row++) {
for (int col = 0; col < verNums; col++) {
if(Integer.MAX_VALUE == edges[row][col]){
System.out.print("X");
System.out.print(" ");
continue;
}
System.out.print(edges[row][col]);
System.out.print(" ");
}
System.out.println();
}
}
}
public class Test { public static void main(String[] args){ List<Vertex> vertexs = new ArrayList<Vertex>(); Vertex a = new Vertex("A", 0); Vertex b = new Vertex("B"); Vertex c = new Vertex("C"); Vertex d = new Vertex("D"); Vertex e = new Vertex("E"); Vertex f = new Vertex("F"); vertexs.add(a); vertexs.add(b); vertexs.add(c); vertexs.add(d); vertexs.add(e); vertexs.add(f); int[][] edges = { {Integer.MAX_VALUE,6,3,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE}, {6,Integer.MAX_VALUE,2,5,Integer.MAX_VALUE,Integer.MAX_VALUE}, {3,2,Integer.MAX_VALUE,3,4,Integer.MAX_VALUE}, {Integer.MAX_VALUE,5,3,Integer.MAX_VALUE,5,3}, {Integer.MAX_VALUE,Integer.MAX_VALUE,4,5,Integer.MAX_VALUE,5}, {Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,3,5,Integer.MAX_VALUE} }; Graph graph = new Graph(vertexs, edges); graph.printGraph(); graph.search(); } }
以上がJava での最短パス アルゴリズムのためのダイクストラ アルゴリズムの実装の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

Java での日付までのタイムスタンプに関するガイド。ここでは、Java でタイムスタンプを日付に変換する方法とその概要について、例とともに説明します。

Java は、初心者と経験豊富な開発者の両方が学習できる人気のあるプログラミング言語です。このチュートリアルは基本的な概念から始まり、高度なトピックに進みます。 Java Development Kit をインストールしたら、簡単な「Hello, World!」プログラムを作成してプログラミングを練習できます。コードを理解したら、コマンド プロンプトを使用してプログラムをコンパイルして実行すると、コンソールに「Hello, World!」と出力されます。 Java の学習はプログラミングの旅の始まりであり、習熟が深まるにつれて、より複雑なアプリケーションを作成できるようになります。

カプセルは3次元の幾何学的図形で、両端にシリンダーと半球で構成されています。カプセルの体積は、シリンダーの体積と両端に半球の体積を追加することで計算できます。このチュートリアルでは、さまざまな方法を使用して、Javaの特定のカプセルの体積を計算する方法について説明します。 カプセルボリュームフォーミュラ カプセルボリュームの式は次のとおりです。 カプセル体積=円筒形の体積2つの半球体積 で、 R:半球の半径。 H:シリンダーの高さ(半球を除く)。 例1 入力 RADIUS = 5ユニット 高さ= 10単位 出力 ボリューム= 1570.8立方ユニット 説明する 式を使用してボリュームを計算します。 ボリューム=π×R2×H(4
