解决最短路径的Dijkstra算法详解,附加Java代码
1. 最短路徑問(wèn)題
最短路徑問(wèn)題是生活中經(jīng)常碰到的一類問(wèn)題,如機(jī)器人路徑規(guī)劃,數(shù)學(xué)競(jìng)賽以及真實(shí)的工程施工問(wèn)題;甚至是我們程序員筆試必刷算法題。其實(shí)問(wèn)題很簡(jiǎn)單,就是有很多個(gè)節(jié)點(diǎn),我們要計(jì)算出一個(gè)初始點(diǎn)到各個(gè)節(jié)點(diǎn)的最短距離(或者得到最短路徑的表示),如下圖,怎么找出A點(diǎn)到其它各個(gè)點(diǎn)的最短路徑及距離? 人眼掃描得到的結(jié)果:A到B、C、D……G距離為 [4, 14, 7, 7, 10, 12],人眼對(duì)付7個(gè)點(diǎn)還是綽綽有余的,什么?你掃描的結(jié)果和我不一樣?那咱們還是分析一下原理,然后寫個(gè)代碼來(lái)處理一下。
2. Dijkstra算法?
2.1 基本原理:有一個(gè)數(shù)組記錄了各個(gè)節(jié)點(diǎn)到初始節(jié)點(diǎn)的距離,該數(shù)組初始值是無(wú)窮大,然后如果選擇A點(diǎn)作為起始點(diǎn),那么修改數(shù)組中A到A的距離為0,并且更新那些與A直接連接的節(jié)點(diǎn)值,并把A標(biāo)記為已訪問(wèn),接下來(lái),從距離數(shù)組中選擇距離最小值,也就是B點(diǎn),循環(huán)...
假設(shè)我們是要計(jì)算其它各點(diǎn)和A點(diǎn)的最短距離。
2.2 代碼編寫
我們大腦很容易分析這種7個(gè)點(diǎn)的最短路徑,那如果是成百上千個(gè)點(diǎn),錯(cuò)綜復(fù)雜,我們大腦可能是不夠用,通過(guò)代碼是最有效的解決辦法,但代碼邏輯也有點(diǎn)難理解,接下來(lái)就好好地理解一下。
2.2.1 數(shù)據(jù)初始化
我們先將圖中的各個(gè)點(diǎn)以及它們之間的路徑距離轉(zhuǎn)化成二維數(shù)組,如下圖。
2.2.2? 結(jié)果記錄初始化
為了保存結(jié)果,我們得對(duì)記錄結(jié)果的數(shù)組進(jìn)行初始化。主要有兩個(gè):一個(gè)是記錄哪些點(diǎn)到A點(diǎn)的距離已經(jīng)確定下來(lái)的數(shù)組,另一個(gè)是記錄每個(gè)點(diǎn)到A點(diǎn)的距離。
2.2.3 初始點(diǎn)的選擇
我們這里計(jì)算各個(gè)點(diǎn)到A點(diǎn)的最短距離。
2.2.4 循環(huán)計(jì)算每個(gè)點(diǎn)和A點(diǎn)的距離,更新distance數(shù)組以及isVisit數(shù)組
2.2.5 運(yùn)行結(jié)果
2.2.6?代碼的話,由于變量和數(shù)組有點(diǎn)多,所以不太容易理解,而且也不太好分析,所以需要同學(xué)們自己耐心對(duì)照2.1基本原理理解,因?yàn)?.1的思路還是比較簡(jiǎn)單清晰,理解思路之后,再來(lái)理解代碼好一些。
3. 完整的Java代碼如下
public static void main(String[] args) {int inf = 100;// 初始化節(jié)點(diǎn)數(shù)為7int node = 7;// 各個(gè)點(diǎn)之間的路徑長(zhǎng)度,inf表示不連通int[][] map = {// 從左往右,從上往下依次表示A、B、C、D、E、F、G{inf, 4, inf, inf, 7, inf, inf},{4, inf, 15, 3, inf, inf, inf},{inf, 15, inf, inf, inf, inf, 2 },{inf, 3, inf, inf, 5, 3, 5 },{7, inf, inf, 5, inf, 6, inf},{inf, inf, inf, 3, 6, inf, inf},{inf, inf, 2, 5, inf, inf, inf}};// 記錄哪些點(diǎn)已經(jīng)確定了,確定為true,否則為默認(rèn)值falseboolean[] isVisit = new boolean[node];// 記錄每個(gè)點(diǎn)距離初始點(diǎn)的距離int[] distance = new int[node];// 初始值為inf,表示無(wú)窮大Arrays.fill(distance, inf);// 選擇A作為初始點(diǎn),0下標(biāo)代表A,int initNode = 0;// A點(diǎn)到自己的距離為0distance[initNode] = 0;// 同時(shí)將isVisit數(shù)組元素A的下標(biāo)0設(shè)置為true,表示A點(diǎn)已確定isVisit[initNode] = true;int currNode = initNode;int certainDistance = distance[currNode];// 只需計(jì)算其余6個(gè)點(diǎn)距離A點(diǎn)的距離,每次循環(huán)得到一個(gè)點(diǎn),循環(huán)6次即可for (int loop = 1; loop < node; loop++) {// 循環(huán)計(jì)算和currNode有關(guān)系節(jié)點(diǎn)的距離,第一次currNode是A點(diǎn)for (int i = 0; i < map[currNode].length; i++) {// 以探索點(diǎn)距初始點(diǎn)的距離加上各點(diǎn)和探索點(diǎn)的距離更新distance矩陣int tmp = certainDistance + map[currNode][i];if(tmp < distance[i]){distance[i] = tmp;}}// 挑選還未訪問(wèn),并且距離初始點(diǎn)最近的點(diǎn)作為探索點(diǎn)currNode = getMin(distance, isVisit, inf);// 將該探索點(diǎn)標(biāo)記為true“已訪問(wèn)”,isVisit[currNode] = true;// 并且得到該點(diǎn)和A點(diǎn)的距離certainDistance = distance[currNode];}char[] str = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};for (int i = 0; i < node; i++) {System.out.println(str[i] + "到" + str[initNode] + "的距離為 " + distance[i]);}}static int getMin(int[] dis, boolean[] isVisit, int inf){int min = -1;int minVal = inf;for (int i = 0; i < dis.length; i++) {// 掃描isVisit還未訪問(wèn)的節(jié)點(diǎn),并且該節(jié)點(diǎn)是distance矩陣最小的數(shù)if((!isVisit[i]) && (dis[i] < minVal)){minVal = dis[i];min = i;}}return min;}總結(jié)
以上是生活随笔為你收集整理的解决最短路径的Dijkstra算法详解,附加Java代码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 手把手详解堆排序,堆就这么难懂?没有人看
- 下一篇: 循环队列真的没那么难,就那么几个注意点,