数据结构与算法&&图论(深度优先遍历,广度优先遍历,联通分量,最短路径)

对于图,我们一般有两种表示方法,稀疏图与稠密图。对于稠密图我们可以用一个二维数组来表示,而对于稀疏图,我们可以用一个集合类型的数组来存放,虽然表示方法不同,但是对它的操作都是一样的。下面我们来看一看对于图如何进行遍历,以及他能够解决哪些问题?

深度优先遍历:

8ffda76aa43b4bc18b1943106f4e9089-dfs.png
1、下面我们对图进行深度优先遍历,顺便求图的联通分量,以及任意两点通过其他点是否是相连的?

public class Component {

 private Graph graph;     //图的引用

 private boolean[] visited; //记录顶点是否被访问过

 private int count=0;     //记录图的联通分量

 private int[] id;       //用来判断图是否是相连的

 public Integer getCount() {
	return count;
  }
/**构造函数*/
 public Component(Graph graph) {
     /**进行初始化*/
     this.graph = graph;
     visited = new boolean[graph.n()];
     id = new int[graph.n()];
     for(int i=0;i;i++){
	 visited[i] = false;
         id[i] = -1;
     }
	 /**从零开始对图进行遍历*/
     for(int i = 0;i<graph.n();i++){
	if(!visited[i]){
	dfs(i);
        count++;     //联通分量加 1
	}

     }
}
 /**递归实现dfs操作*/
 private void dfs(int i) {
    visited[i] = true;
    id[i] = count;     
    for(Integer item:graph.adj(i)){
	 if(!visited[item]){
	    dfs(item);
          }

       }

    }
	
/**判断图中任意两点是否相连*/	
public boolean connected(int v, int w){

   return id[v] == id[w];
  } 

 }

2、解决第二个问题,计算从某一点到另一点的路径:

public class Path {

 /**图的引用*/
  private Graph G;

  /**起始点*/
  private  int s;

  /**记录dfs的过程中节点是否被访问*/
  private boolean[]  visited;

  /**记录路径,表示我是从哪一个定点到我这儿的 */
  private int[] from;

 public Path(Graph graph, int s) {
   this.G = graph;
   visited = new boolean[graph.n()];
   from = new int[G.n()];
  for(int i=0;i<G.n();i++){
	visited[i]=false;
        from[i] = -1;
  }
       this.s = s;

      dfs(s);
  }
/***图的深度优先遍历*/
  private void dfs(int v) {
    visited[v]=true;
    for(int i:G.adj(v)){
       if(!visited[i]){
	 from[i]=v;
         dfs(i);
              }
	}
   }
/**查询从s点到w点的路径, 存放在vec中**/
  public Vector path(int w){
      Stack s = new Stack();
      int p=w;
       while(p!=-1){
	s.push(p);
        p=from[p];
       }
   Vector vector = new Vector<>();
   while (!s.empty()){
       vector.add(s.pop());
       }
   return vector;
  }

	/**打印路径*/
  public void showPath(int w){

    Vector vector = this.path(w);

     for(int i=0;i;i++){
	System.out.print(vector.elementAt(i));
         if(i==vector.size()-1){
	    System.out.print("");
          }
	else{
	     System.out.print("->");
          }
	}
   }

广度优先遍历:

3、当我们使用深度优先遍历寻找图示0到6的路径为:0->5->3->4->6,很显然这不是一条最短路径,那么如何找到最短路径呢?我们可以使用广度优先遍历,简称bfs(Breadth First Search)。同时我们还要借助于队列这种数据结构,下面我们来看一下思路
9eb4b5bb302f427aa8652625e44eccb1.png

public class ShortestPath {
 /**图的引用*/
  private Graph G;
  /**起始点*/
  private  int s;
  /**记录bfs的过程中节点是否被访问*/
  private boolean[]  visited;
  /**记录路径, from[i]表示查找的路径上i的上一个节点*/
  private int[] from;
  /**构造函数, 寻路算法, 寻找图graph从s点到其他点的路径*/
  public ShortestPath(Graph graph, int s) {
     this.G = graph;
     this.s = s;
     visited = new boolean[graph.n()];
     from = new int[G.n()];
      for(int i=0;i<G.n();i++){
	 visited[i]=false;
        from[i] = -1;
   }
   Queue queue = new LinkedList();
   queue.add(s);
   visited[s]=true;
   while(queue.size()!=0){
	int a = queue.poll();
        for(int i:graph.adj(a)){
	    if(!visited[i]){
	      queue.add(i);
              visited[i] = true;
              from[i] =a;

             }

	  }
      }

   }
	/**查询从s点到w点的路径, 存放在vec中**/
  public Vector path(int w){
    Stack s = new Stack();
    int p=w;
    while(p!=-1){
    s.push(p);
     p=from[p];
  }
   Vector vector = new Vector<>();
    while (!s.empty()){
    vector.add(s.pop());
  }
   return vector;
  }
  
/**打印路径*/
  public void showPath(int w){
       Vector vector = this.path(w);
       for(int i=0;i;i++){
	 System.out.print(vector.elementAt(i));
          if(i==vector.size()-1){
	     System.out.print("");
            }
	  else{
	     System.out.print("->");
              }
	}
		System.out.println();
  }

这样我们就能找到0-6的最短路径是0-6

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值