java计算稀疏图连通分量及两点路径、最短路径

博客初感言:

我的第一篇博客,好激动啊,以前只是经常看别的大侠的博客,还从来没想过自己写,以前我记知识点或学习笔记都是直接写在本子上的,感觉这样看起来更方便,不过还是想尝试一下,分享自己的学习经验。希望自己能坚持下去! 奋斗

计算稀疏图连通分量

 我写了实现稠密图和稀疏图的两个类,目前只写了计算稀疏图连通分量的算法,代码如下:
//稠密图--邻接矩阵
public class DenseGraph{
	private int n,m; //顶点,边
	private boolean isdirected; //是否有向图
	private ArrayList<ArrayList<Boolean>> g=new ArrayList<ArrayList<Boolean>>();  //二维矩阵
	
	public DenseGraph(int n, boolean isdirected) {
		this.n = n;
		this.m=0;      //边
		this.isdirected = isdirected;
		for(int i=0;i<n;i++){
			ArrayList<Boolean> arr=new ArrayList<Boolean>(n);
			for(int j=0;j<n;j++)
				arr.add(false);
			g.add(arr);
		}
	}
	public int V(){return n;} 
	public int E(){return m;}
	//添加边
	public void addEdge(int v,int w){
		assert(v>=0&&v<n);
		assert(w>=0&&w<n);
		if(hasEdge(v,w))   //防止有边情况下再m++,所以先判断下
			return;
		ArrayList<Boolean> arr=g.get(v);
		arr.set(w, true);
		if(!isdirected){     //若不是有向图
			ArrayList<Boolean> sarr=g.get(w);
			sarr.set(v, true);
		}
		m++; 
	}
	public ArrayList<Boolean> getGraph(int n){
		return g.get(n);
	}
	
	public boolean hasEdge(int v,int w){
		assert(v>=0&&v<n);
		assert(w>=0&&w<n);
		ArrayList<Boolean> arr=g.get(v);
		boolean a=arr.get(w);
		return a;
	}
	public static void main(String[] args) {
		int N=20;  //顶点
		int M=100;   //边
		DenseGraph sg=new DenseGraph(N,false);
		for(int i=0;i<M;i++){
			sg.addEdge(new Random().nextInt(20), new Random().nextInt(20));
		}
		System.out.print("  ");
		for(int i=0;i<N;i++){
			String s=i>=10?(" "+i):("  "+i);
			System.out.print(s);
		}
		System.out.println();
		for(int i=0;i<N;i++){
			System.out.print(i+" ");
			ArrayList<Boolean> srr=sg.getGraph(i);
			Iterator<Boolean> ite=srr.iterator();
			if(i<10)
				System.out.print(" ");
			while(ite.hasNext())
				System.out.print(" "+(ite.next()?1:0)+" ");
			System.out.println();
		}
	}

}
//稀疏图---邻接表
public class SparseGraph{
	private int n,m; //顶点,边
	private boolean isdirected; //是否有向图
	private ArrayList<ArrayList<Integer>> g=new ArrayList<ArrayList<Integer>>();  //邻接表
	
	
	public SparseGraph(int n, boolean isdirected) {
		this.n = n;
		this.m=0;
		this.isdirected = isdirected;
		for(int i=0;i<n;i++){
			ArrayList<Integer> arr=new ArrayList<Integer>();
			g.add(arr);
		}
	}

	public int V(){return n;} 
	public int E(){return m;}
	
	public ArrayList<Integer> getGraph(int n){
		return g.get(n);
	}
	
	public void addEdge(int v,int w){
		assert(v>=0&&v<n);
		assert(w>=0&&w<n);
		if(hasEdge(v,w))     //排除平行边
			return;
		if(v!=w){
			ArrayList<Integer> arr=g.get(v);
			arr.add(w);
			m++;
		}
		if(v!=w&&!isdirected){      //且是无向图
			ArrayList<Integer> srr=g.get(w);
			srr.add(v);
		}	
	}
	public boolean hasEdge(int v,int w){
		assert(v>=0&&v<n);
		assert(w>=0&&w<n);
		ArrayList<Integer> arr=g.get(v);
		for(int i=0;i<arr.size();i++){		
			if(arr.get(i)==w)
				return true;
		}
		return false;
	}
	
	public static void main(String[] args) {
		int N=30;  //顶点
		int M=50;   //边
		SparseGraph sg=new SparseGraph(N,false);
		for(int i=0;i<M;i++){
			sg.addEdge(new Random().nextInt(N), new Random().nextInt(N));
		}
		for(int i=0;i<N;i++){
			System.out.print(i+" :");
			ArrayList<Integer> srr=sg.getGraph(i);
			Iterator<Integer> ite=srr.iterator();
			while(ite.hasNext())
				System.out.print(ite.next()+" ");
			System.out.println();
		}
		Component c=new Component(sg);
		System.out.println("该图的连通分量: "+c.count());
	}



}

Component类:

//利用深度优先遍历求图的连通分量
public class Component{
	private SparseGraph G;       //图
	private boolean[] visited;    //记录每个节点是否被访问过
	private int ccount;    //记录该图有多少个连通分量
	private void dfs(int v){
		visited[v]=true;
		ArrayList<Integer> arr= G.getGraph(v);
		Iterator<Integer> ite=arr.iterator();
		while(ite.hasNext()){
			int next=ite.next();
			if(!visited[next])
				dfs(next);
		}
		
	}
	public Component(SparseGraph g) {
		G = g;
		visited=new boolean[G.V()];
		ccount=0;
		for(int i=0;i<G.V();i++){
			visited[i]=false;
		}
		for(int i=0;i<G.V();i++){
			if(!visited[i]){  
				dfs(i);
				++ccount;
			}
		}
	}
	public int count(){
		return ccount;
    }

}

我利用的是深度优先遍历算法求稀疏图的连通分量


类Path:通过深度优先遍历来获得路径

public class Path {
	private SparseGraph sg;
	private int s;         //起点
	private boolean[] visited;
	private int[] from;
	//通过深度优先遍历来获得路径
	private void dfs(int v){
		visited[v]=true;
		ArrayList<Integer> arr= sg.getGraph(v);
		Iterator<Integer> ite=arr.iterator();
		while(ite.hasNext()){
			int next=ite.next();
			if(!visited[next]){
				from[next]=v;      //next是从v遍历过来的
				dfs(next);
			}
		}
		
	}
	public Path(SparseGraph sg, int s) {
		assert(s>=0&&s<sg.V());
		this.sg = sg;
		this.s = s;
		visited=new boolean[sg.V()];
		from=new int[sg.V()];
		for(int i=0;i<sg.V();i++){
			visited[i]=false;
			from[i]=-1;
		}
		//寻路算法
		dfs(s);
	}
	//s到w连不连通
	public boolean hasPath(int w){    //终点w
		assert(w>=0&&w<sg.V());
		return visited[w];
	}
	//将路径存入arr中
	public void path(int w,ArrayList<Integer> arr){
		Stack<Integer> s =new Stack<Integer>();
		int p=w;
		while(p!=-1){
			s.push(p);
			p=from[p];
		}
		arr.clear();
		while(!s.isEmpty()){
			arr.add(s.peek());
			s.pop();
		}
	}
	public void showPath(int w){
		ArrayList<Integer> arr =new ArrayList<Integer>();
		path(w,arr);
		for(int i=0;i<arr.size();i++){
			System.out.print(arr.get(i));
			if(i!=arr.size()-1){
				System.out.print("->");
			}
		}
		
	}
	
}

类ShortestPath:通过广度优先遍历(层序遍历)求出无权图的最短路径

//通过广度优先遍历(层序遍历)求出无权图的最短路径
public class ShortestPath {
	private SparseGraph sg;
	private int s;         //起点
	private boolean[] visited;
	private int[] from;
	private int[] ord; //记录起点s到每一个节点的最短路径
	
	public ShortestPath(SparseGraph sg, int s) {
		assert(s>=0&&s<sg.V());
		this.sg = sg;
		this.s = s;
		visited=new boolean[sg.V()];
		from=new int[sg.V()];
		ord=new int[sg.V()];
		for(int i=0;i<sg.V();i++){
			visited[i]=false;
			from[i]=-1;
			ord[i]=-1;
		}
		Queue<Integer> q=new LinkedList<Integer>();    //通过LinkedList来实现队列
		//无权图最短路径算法
		q.offer(s);
		visited[s]=true;
		ord[s]=0;
		while(!q.isEmpty()){
			int v=q.peek();
			q.poll();
			ArrayList<Integer> arr=sg.getGraph(v);
			Iterator<Integer> ite=arr.iterator();
			while(ite.hasNext()){
				int next=ite.next();
				if(!visited[next]){
					q.offer(next);
					visited[next]=true;
					from[next]=v;
					ord[next]=ord[v]+1;
				}
			}
		}
		
	}
	
	//s到w连不连通
	public boolean hasPath(int w){    //终点w
		assert(w>=0&&w<sg.V());
		return visited[w];
	}
	//将路径存入arr中
	public void path(int w,ArrayList<Integer> arr){
		Stack<Integer> s =new Stack<Integer>();
		int p=w;
		while(p!=-1){
			s.push(p);
			p=from[p];
		}
		arr.clear();
		while(!s.isEmpty()){
			arr.add(s.peek());
			s.pop();
		}
	}
	
	public void showPath(int w){
		ArrayList<Integer> arr =new ArrayList<Integer>();
		path(w,arr);
		for(int i=0;i<arr.size();i++){
			System.out.print(arr.get(i));
			if(i!=arr.size()-1){
				System.out.print("->");
			}
		}
		
	}
	//起点s到终点w的最短路径长度是多少
	public int length(int w){
		assert(w>=0&&w<sg.V());
		return ord[w];
	}
	
	
	
}

修改后的main方法

	public static void main(String[] args) {
		int N=30;  //顶点
		int M=50;   //边
		SparseGraph sg=new SparseGraph(N,false);
		for(int i=0;i<M;i++){
			sg.addEdge(new Random().nextInt(N), new Random().nextInt(N));
		}
		for(int i=0;i<N;i++){
			System.out.print(i+" :");
			ArrayList<Integer> srr=sg.getGraph(i);
			Iterator<Integer> ite=srr.iterator();
			while(ite.hasNext())
				System.out.print(ite.next()+" ");
			System.out.println();
		}
		Component c=new Component(sg);
		System.out.println("该图的连通分量: "+c.count());
		
		
		int start=4;
		int end=27;
		Path p=new Path(sg,start);   
		ShortestPath sp=new ShortestPath(sg,start);
		if(p.hasPath(end)){
			System.out.println("从"+start+"到"+end+"的路径为");
			p.showPath(end);
		}
		System.out.println();
		if(sp.hasPath(end)){
			System.out.println("从"+start+"到"+end+"的最短路径为");
			sp.showPath(end);
		}
		
	}


结果如图:


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值