Java常用圖形演算法
阿新 • • 發佈:2019-02-16
/***
* Dijkstra演算法
* 演算法步驟:
* 1、第一輪,可以計算出,2、3、4、5、6到原點1的距離分別為:[7, 9, -1, -1, 14]。-1表示無窮大。
* 取其中最小的,為7,即可以確定1的最短路徑為0,2為下一輪的前驅節點。同時確定2節點的最短路徑為7,路線:1->2。
* 2、第二輪,取2節點為前驅節點,按照前驅節點的最短距離加上該節點與前驅節點的距離計算新的最短距離,
* 可以得到3,4,5,6節點到原點的距離為:[17, 22, -1, -1],此時需要將這一輪得到的結果與上一輪的比較,3節點:17 > 9,
* 最短路徑仍然為9;4節點:22 < 無窮大,重新整理4節點的最短路徑為22;5節點:不變,仍然為無窮大;6節點:14 < 無窮大,取14,不變。
* 則可以得到本輪的最短距離為:[9, 22, -1, 14],取最短路徑最小的節點,為3,作為下一輪的前驅節點。同時確定3節點的最短路徑為9,路線:1->3。
* 3、第三輪,同上,以3為前驅節點,得到4,5,6的計算距離為:[20, -1, 11],按照取最短路徑的原則,與上一輪的進行比較,重新整理為:[20, –1, 11],
* 選定6為下一輪的前驅節點。同時取定6的最短路徑為11,路線:1->3->6。
* 4、第四輪,同上,以6為前驅節點,得到4和5的計算距離為[20, 20],與上一輪進行比較,重新整理後為[20, 20],二者相等只剩下兩個節點,並且二者想等,
* 剩下的計算已經不需要了。則兩個節點的最短路徑都為20。整個計算結束。4的最短路徑為20,路線:1->3->4。5的最短路徑為20,路線:1->3->6->5。
* 參考連結:http://developer.51cto.com/art/201406/443115.htm
* http://blog.csdn.net/gamer_gyt/article/details/47184081
* */
public class Dijkstra {
public static final int M = -1;
static int[][] map = {
{ 0, 7, 9, M, M, 14 },
{ 7, 0, 10, 15, M, M },
{ 9, 10, 0, 11, M, 2 },
{ M, 15, 11, 0, 6, M },
{ M, M, M, 6, 0, 9 },
{ 14, M, 2, M, 9, 0 }
};
static int n =map.length; //頂點的個數
static int[] shortest = new int[n]; //存放從start到其他節點的最短路徑
static boolean[] visited = new boolean[n]; //標記當前該頂點的最短路徑是否已經求出,true表示已經求出
public static void main(String[] args) {
int orig = 0; //起始點
//尋找最短路徑
int[] shortPath = dijkstra_alg(orig);
if(shortPath == null){
return;
}
for(int i=0; i< shortPath.length; i++){
System.out.println("從" + (orig + 1) + "出發到" + (i + 1) + "的最短距離為:"+ shortPath[i]);
}
}
private static int[] dijkstra_alg(int orig) {
// TODO Auto-generated method stub
// 初始化,第一個頂點求出
shortest[orig] = 0;
visited[orig] = true;
for(int count = 0; count != n-1; count ++)
{
//選出一個距離初始頂點最近的為標記頂點
int k = M;
int min = M;
for(int i =0; i< n ; i++)//遍歷每一個頂點
{
if( !visited[i] && map[orig][i] != M) //如果該頂點未被遍歷過且與orig相連
{
if(min == -1 || min > map[orig][i]) //找到與orig最近的點
{
min = map[orig][i];
k = i;
}
}
}
//正確的圖生成的矩陣不可能出現K== M的情況
if(k == M)
{
System.out.println("the input map matrix is wrong!");
return null;
}
shortest[k] = min;
visited[k] = true;
//以k為中心點,更新oirg到未訪問點的距離
for (int i = 0; i < n; i++)
{
if (!visited[i] && map[k][i] != M)
{
int callen = min + map[k][i];
if (map[orig][i] == M || map[orig][i] > callen)
{
map[orig][i] = callen;
}
}
}
}
return shortest;
}
}
* Dijkstra演算法
* 演算法步驟:
* 1、第一輪,可以計算出,2、3、4、5、6到原點1的距離分別為:[7, 9, -1, -1, 14]。-1表示無窮大。
* 取其中最小的,為7,即可以確定1的最短路徑為0,2為下一輪的前驅節點。同時確定2節點的最短路徑為7,路線:1->2。
* 2、第二輪,取2節點為前驅節點,按照前驅節點的最短距離加上該節點與前驅節點的距離計算新的最短距離,
* 可以得到3,4,5,6節點到原點的距離為:[17, 22, -1, -1],此時需要將這一輪得到的結果與上一輪的比較,3節點:17 > 9,
* 最短路徑仍然為9;4節點:22 < 無窮大,重新整理4節點的最短路徑為22;5節點:不變,仍然為無窮大;6節點:14 < 無窮大,取14,不變。
* 則可以得到本輪的最短距離為:[9, 22, -1, 14],取最短路徑最小的節點,為3,作為下一輪的前驅節點。同時確定3節點的最短路徑為9,路線:1->3。
* 3、第三輪,同上,以3為前驅節點,得到4,5,6的計算距離為:[20, -1, 11],按照取最短路徑的原則,與上一輪的進行比較,重新整理為:[20, –1, 11],
* 選定6為下一輪的前驅節點。同時取定6的最短路徑為11,路線:1->3->6。
* 4、第四輪,同上,以6為前驅節點,得到4和5的計算距離為[20, 20],與上一輪進行比較,重新整理後為[20, 20],二者相等只剩下兩個節點,並且二者想等,
* 剩下的計算已經不需要了。則兩個節點的最短路徑都為20。整個計算結束。4的最短路徑為20,路線:1->3->4。5的最短路徑為20,路線:1->3->6->5。
* 參考連結:http://developer.51cto.com/art/201406/443115.htm
* http://blog.csdn.net/gamer_gyt/article/details/47184081
* */
public class Dijkstra {
public static final int M = -1;
static int[][] map = {
{ 0, 7, 9, M, M, 14 },
{ 7, 0, 10, 15, M, M },
{ 9, 10, 0, 11, M, 2 },
{ M, 15, 11, 0, 6, M },
{ M, M, M, 6, 0, 9 },
{ 14, M, 2, M, 9, 0 }
};
static int n =map.length; //頂點的個數
static int[] shortest = new int[n]; //存放從start到其他節點的最短路徑
static boolean[] visited = new boolean[n]; //標記當前該頂點的最短路徑是否已經求出,true表示已經求出
public static void main(String[] args) {
int orig = 0; //起始點
//尋找最短路徑
int[] shortPath = dijkstra_alg(orig);
if(shortPath == null){
return;
}
for(int i=0; i< shortPath.length; i++){
System.out.println("從" + (orig + 1) + "出發到" + (i + 1) + "的最短距離為:"+ shortPath[i]);
}
}
private static int[] dijkstra_alg(int orig) {
// TODO Auto-generated method stub
// 初始化,第一個頂點求出
shortest[orig] = 0;
visited[orig] = true;
for(int count = 0; count != n-1; count ++)
{
//選出一個距離初始頂點最近的為標記頂點
int k = M;
int min = M;
for(int i =0; i< n ; i++)//遍歷每一個頂點
{
if( !visited[i] && map[orig][i] != M) //如果該頂點未被遍歷過且與orig相連
{
if(min == -1 || min > map[orig][i]) //找到與orig最近的點
{
min = map[orig][i];
k = i;
}
}
}
//正確的圖生成的矩陣不可能出現K== M的情況
if(k == M)
{
System.out.println("the input map matrix is wrong!");
return null;
}
shortest[k] = min;
visited[k] = true;
//以k為中心點,更新oirg到未訪問點的距離
for (int i = 0; i < n; i++)
{
if (!visited[i] && map[k][i] != M)
{
int callen = min + map[k][i];
if (map[orig][i] == M || map[orig][i] > callen)
{
map[orig][i] = callen;
}
}
}
}
return shortest;
}
}