java中如何遍历最短路径长度邻接矩阵

Python013

java中如何遍历最短路径长度邻接矩阵,第1张

package test

import java.util.ArrayList

import java.util.List

/**

 * java-用邻接矩阵求图的最短路径、最长途径。弗洛伊德算法

 */

public class FloydInGraph {

 private static int INF=Integer.MAX_VALUE

 private int[][] dist

 private int[][] path

 private List<Integer> result=new ArrayList<Integer>()

 public FloydInGraph(int size){

  this.path=new int[size][size]

  this.dist=new int[size][size]

 }

 public void findPath(int i,int j){

  int k=path[i][j]

  if(k==-1)return

  findPath(i,k)

  result.add(k)

  findPath(k,j)

 }

 public  void findCheapestPath(int begin,int end,int[][] matrix){

  floyd(matrix)

  result.add(begin)

  findPath(begin,end)

  result.add(end)

 }

 public  void floyd(int[][] matrix){

  int size=matrix.length

  for(int i=0i<sizei++){

   for(int j=0j<sizej++){

    path[i][j]=-1

    dist[i][j]=matrix[i][j]

   }

  }

  for(int k=0k<sizek++){

   for(int i=0i<sizei++){

    for(int j=0j<sizej++){

     if(dist[i][k]!=INF&&

      dist[k][j]!=INF&&

      dist[i][k]+dist[k][j]<dist[i][j]){//dist[i][k]+dist[k][j]>dist[i][j]-->longestPath

      dist[i][j]=dist[i][k]+dist[k][j]

      path[i][j]=k

     }

    }

   }

  }

  

 }

 public static void main(String[] args) {

  FloydInGraph graph=new FloydInGraph(5)

  int[][] matrix={

    {INF,30,INF,10,50},

    {INF,INF,60,INF,INF},

    {INF,INF,INF,INF,INF},

    {INF,INF,INF,INF,30},

    {50,INF,40,INF,INF},

  }

  int begin=0

  int end=4

  graph.findCheapestPath(begin,end,matrix)

  List<Integer> list=graph.result

  System.out.println(begin+" to "+end+",the cheapest path is:")

  System.out.println(list.toString())

  System.out.println(graph.dist[begin][end])

 }

}

用编程实现图的存储一般有常见的有两种方式,第一种是邻接链表、第二种就是邻接矩阵。

邻接链表就是将图中的每一个点都单独作为一个单独链表的起点,为每个顶点保存一个链表。链表的每一个节点都记录了与之相邻的节点的信息。

邻接矩阵就是将图转换成一个二维数组,数组的x和y均表示图中每个节点到其他节点的连接状况,能连通用一种状态表示,不能连通用另外一中方式表示,这样就形成了一个笛卡尔积。也就是一个二维数组。

import java.util.Scanner

import java.util.Stack

public class DFS

{

// 存储节点信息

private char[] vertices

// 存储边信息(邻接矩阵)

private int[][] arcs

// 图的节点数

private int vexnum

// 记录节点是否已被遍历

private boolean[] visited

// 初始化

public DFS(int n)

{

vexnum = n

vertices = new char[n]

arcs = new int[n][n]

visited = new boolean[n]

for(int i = 0 i < vexnum i++)

{

for(int j = 0 j < vexnum j++)

{

arcs[i][j] = 0

}

}

}

// 添加边(无向图)

public void addEdge(int i, int j)

{

// 边的头尾不能为同一节点

if(i == j)

return

arcs[i - 1][j - 1] = 1

arcs[j - 1][i - 1] = 1

}

// 设置节点集

public void setVertices(char[] vertices)

{

this.vertices = vertices

}

// 设置节点访问标记

public void setVisited(boolean[] visited)

{

this.visited = visited

}

// 打印遍历节点

public void visit(int i)

{

System.out.print(vertices[i] + " ")

}

// 从第i个节点开始深度优先遍历

private void traverse(int i)

{

// 标记第i个节点已遍历

visited[i] = true

// 打印当前遍历的节点

visit(i)

// 遍历邻接矩阵中第i个节点的直接联通关系

for(int j = 0 j < vexnum j++)

{

// 目标节点与当前节点直接联通,并且该节点还没有被访问,递归

if(arcs[i][j] == 1 && visited[j] == false)

{

traverse(j)

}

}

}

// 图的深度优先遍历(递归)

public void DFSTraverse(int start)

{

// 初始化节点遍历标记

for(int i = 0 i < vexnum i++)

{

visited[i] = false

}

// 从没有被遍历的节点开始深度遍历

for(int i = start - 1 i < vexnum i++)

{

if(visited[i] == false)

{

// 若是连通图,只会执行一次

traverse(i)

}

}

}

// 图的深度优先遍历(非递归)

public void DFSTraverse2(int start)

{

// 初始化节点遍历标记

for(int i = 0 i < vexnum i++)

{

visited[i] = false

}

Stack<Integer> s = new Stack<Integer>()

for(int i = start - 1 i < vexnum i++)

{

if(!visited[i])

{

// 连通子图起始节点

s.add(i)

do

{

// 出栈

int curr = s.pop()

// 如果该节点还没有被遍历,则遍历该节点并将子节点入栈

if(visited[curr] == false)

{

// 遍历并打印

visit(curr)

visited[curr] = true

// 没遍历的子节点入栈

for(int j = vexnum - 1 j >= 0 j--)

{

if(arcs[curr][j] == 1 && visited[j] == false)

{

s.add(j)

}

}

}

} while(!s.isEmpty())

}

}

}

public static void main(String[] args)

{

Scanner sc = new Scanner(System.in)

int N, M, S

while(true)

{

System.out.println("输入N M S,分别表示图G的结点数,边数,搜索的起点:")

String line = sc.nextLine()

if(!line.matches("^\\s*([1-9]\\d?|100)(\\s+([1-9]\\d?|100)){2}\\s*$"))

{

System.out.print("输入错误,")

continue

}

String[] arr = line.trim().split("\\s+")

N = Integer.parseInt(arr[0])

M = Integer.parseInt(arr[1])

S = Integer.parseInt(arr[2])

break

}

DFS g = new DFS(N)

char[] vertices = new char[N]

for(int i = 0 i < N i++)

{

vertices[i] = (i + 1 + "").charAt(0)

}

g.setVertices(vertices)

for(int m = 0 m < M m++)

{

System.out.println("输入图G的第" + (m + 1) + "条边,格式为“i j”,其中i,j为结点编号(范围是1~N)")

String line = sc.nextLine()

if(!line.matches("^\\s*([1-9]\\d?|100)\\s+([1-9]\\d?|100)\\s*$"))

{

System.out.print("输入错误,")

m--

continue

}

String[] arr = line.trim().split("\\s+")

int i = Integer.parseInt(arr[0])

int j = Integer.parseInt(arr[1])

g.addEdge(i, j)

}

sc.close()

System.out.print("深度优先遍历(递归):")

g.DFSTraverse(S)

System.out.println()

System.out.print("深度优先遍历(非递归):")

g.DFSTraverse2(S)

}

}