package interview.src;
import java.util.PriorityQueue;
public class My_Graph_2 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//1.Dijstra算法:计算一个节点到其他所有节点的最短路径
String[] nodes = new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I" };
My_Graph_2 grf = new My_Graph_2(nodes.length, nodes);
grf.initGrf();
// grf.printMatrix();
//
// System.out.println("Dijkstra迭代 ---");
// grf.dijkstra(0); //起点是 0
// grf.printDis();
//
// System.out.println();
// System.out.println("Dijkstra优先队列 ---");
// grf.dijkstraPQ();
// grf.printDis();
//2.floyd最短路径,图中各个顶点间的最短路径
int[][] path = new int[nodes.length][grf.matirx.length];
int[][] floy = new int[nodes.length][grf.matirx.length];
// floyd算法获取各个顶点之间的最短距离
grf.floyd(path, floy);
}
//1.Dijstra算法:计算一个节点到其他所有节点的最短路径
// 为了矩阵的输出更直观好看一些,本例中约定,路径权值取值范围为:[1,10],权值为999表示无连通
// 并假设所有权值的和小于999
private final int MAX = 999;
private int total; // 顶点总数
private String[] nodes; // 顶点信息
private int[][] matirx; // 顶点矩阵
private int[] dis; // 源点到各顶点的距离
private boolean[] visited; // 顶点是否已标记
public My_Graph_2(int total, String[] nodes) {
this.total = total;
this.nodes = nodes;
this.matirx = new int[total][total];
this.dis = new int[total];
this.visited = new boolean[total];
}
// 初始化图数据
// 0---1---2---3---4---5---6---7---8---
// A---B---C---D---E---F---G---H---I---
private void initGrf() {
for (int i = 0; i < this.total; i++) {
for (int j = 0; j < this.total; j++) {
if (i == j) {
this.matirx[i][j] = 0;
} else {
this.matirx[i][j] = MAX;
}
}
}
/**
---0 1 2 3 4 5 6 7 8
---A B C D E F G H I
-A|0 2 m 1 3 m m m m 0
-B|m 0 2 m m m m m m 1
-C|m m 0 m m 1 m m m 2
-D|m m m 0 5 m 2 m m 3
-E|m m m m 0 6 m 1 m 4
-F|m m m m m 0 m m 3 5
-G|m m m m m m 0 4 m 6
-H|m m m m m 1 m 0 2 7
-I|m m m m m m m m 0 8
**/
// 手动设置有向路径
// A->B, A->E, A->D
this.matirx[0][1] = 2;
this.matirx[0][4] = 3;
this.matirx[0][3] = 1;
// B->C
this.matirx[1][2] = 2;
// C->F
this.matirx[2][5] = 1;
// D->E, D->G
this.matirx[3][4] = 5;
this.matirx[3][6] = 2;
// E->F, E->H
this.matirx[4][5] = 6;
this.matirx[4][7] = 1;
// F->I
this.matirx[5][8] = 3;
// G->H
this.matirx[6][7] = 4;
// H->F, H->I
this.matirx[7][5] = 1;
this.matirx[7][8] = 2;
}
private void printMatrix() {
for (int i = 0; i < this.total; i++) {
System.out.print("-" + this.nodes[i] + "|");
for (int j = 0; j < this.total; j++) {
System.out.print(String.format("%s", this.matirx[i][j]==999?"m":this.matirx[i][j]) + " ");
}
System.out.println();
}
}
/**
* Dijkstra算法-(迪杰斯特拉)算法之迭代实现
*
* @param s 源点(起点)
*/
public void dijkstra(int s) {
// 初始化
for (int i = 0; i < this.total; i++) {
this.visited[i] = false; // 初始化都未标记
this.dis[i] = this.matirx[s][i]; // 给源点的直接邻接点加上初始权值
}
this.visited[s] = true; // 将源点s加入S集合
this.dis[s] = 0; // 顶点到自身的距离为0,多此一举
int min = -1; // 临时最短距离
int k = -1; // 每次找到距离最短的点
// this.printDis(); //每次都打印距离dis
// 源点s到其它顶点(共total-1个)的最短距离
for (int i = 1; i < this.total; i++) {
// 从当前最新的,源点到其它各顶点的距离信息数组dis[]中,找到一个没有标记过的,
// 并且距离(从源点到该某顶点)最短的顶点
min = MAX;
for (int j = 0; j < this.total; j++) {
if (this.visited[j]==false && this.dis[j] < min) {
min = this.dis[j];
k = j;
}
}
this.visited[k] = true; // 找到的k加入S集合
//距离校正
for (int j = 0; j < this.total; j++) {
if ((this.visited[j] == false) && (this.matirx[k][j] + this.dis[k]) < this.dis[j]) { //最重要部分,j没访问过,且(k到j的距离)+(源点到k的距离) <(源点到j的距离)
this.dis[j] = this.matirx[k][j] + this.dis[k];
}
}
this.printDis(); //打印dis数组
}
}
/**
* Dijkstra算法-(迪杰斯特拉)算法之优先队列实现
*/
public void dijkstraPQ() {
// Item是PriorityQueue中元素,实现了Comparable接口,优先队列用此接口进行排序
class Item implements Comparable<Item> {
public int idx; // 节点在数组的下标
public int weight; // 到该节点的临时最小权值和
public Item(int idx, int weight) {
this.idx = idx;
this.weight = weight;
}
@Override
public int compareTo(Item item) {
if (this.weight == item.weight) {
return 0;
} else if (this.weight < item.weight) {
return -1;
} else {
return 1;
}
}
}
// 值较小的元素总是在优先队列的头部,值较大的元素总是在优先队列的尾部
PriorityQueue<Item> pq = new PriorityQueue<Item>();
pq.offer(new Item(0, 0)); //源点(即起点)入队列
Item itm = null;
while (!pq.isEmpty()) {
itm = pq.poll(); //取出
int idx = itm.idx; // 节点下标
int weight = itm.weight; // 到该节点的最小权值和
// 如果该元素还未标记,则更新dis数组
if (this.visited[idx] == false) {
this.dis[idx] = weight;
}
// 找出该元素(假设A)的所有未标记的邻接点(假设B)
// 则,源点到B的距离可表示为:(源点到A的距离) + (A到B的距离)
// 将源点到B的距离加入到优先队列中
for (int i = 0; i < this.total; i++) {
if (this.visited[i] == false) {
pq.offer(new Item(i, this.dis[idx] + this.matirx[idx][i]));
}
}
}
}
//打印个dis数组
private void printDis() {
for (int t : this.dis) {
System.out.print(t + ",");
}
System.out.println();
}
//2.floyd最短路径,图中各个顶点间的最短路径
/*
* floyd最短路径。
* 即,统计图中各个顶点间的最短路径。
*
* 参数说明:
* path -- 路径。path[i][j]=k表示,"顶点i"到"顶点j"的最短路径会经过顶点k。
* dist -- 长度数组。即,dist[i][j]=sum表示,"顶点i"到"顶点j"的最短路径的长度是sum。
*/
public void floyd(int[][] path, int[][] dist) {
// 初始化
for (int i = 0; i < nodes.length; i++) {
for (int j = 0; j < nodes.length; j++) {
dist[i][j] = matirx[i][j]; // "顶点i"到"顶点j"的路径长度为"i到j的权值"。
path[i][j] = j; //*** "顶点i"到"顶点j"的最短路径是经过顶点j。
}
}
// 计算最短路径
for (int k = 0; k < nodes.length; k++) {
for (int i = 0; i < nodes.length; i++) {
for (int j = 0; j < nodes.length; j++) {
// 如果经过下标为k顶点路径比原两点间路径更短,则更新dist[i][j]和path[i][j]
int tmp = (dist[i][k]==MAX || dist[k][j]==MAX) ? MAX : (dist[i][k] + dist[k][j]);
if (tmp < dist[i][j]) {
// "i到j最短路径"对应的值设,为更小的一个(即经过k)
dist[i][j] = tmp;
// "i到j最短路径"对应的路径,经过k
path[i][j] = path[i][k]; //此时 path[i][k]即为k
}
}
}
}
// 打印floyd最短路径的结果
System.out.printf("floyd dis: \n");
for (int i = 0; i < nodes.length; i++) {
for (int j = 0; j < nodes.length; j++)
System.out.printf("%s ", dist[i][j]==999?"m":dist[i][j]);
System.out.println();
}
// 打印floyd路径结果
System.out.printf("floyd path: \n");
for (int i = 0; i < nodes.length; i++) {
for (int j = 0; j < nodes.length; j++)
// System.out.printf("%s ", dist[i][j]==999?"m":dist[i][j]);
System.out.print(path[i][j]+" ");
System.out.println();
}
}
}
My_Graph2 DFS BFS
最新推荐文章于 2022-02-25 16:57:24 发布