蓝桥杯JAVA-11.图的存储方式(JAVA实现)

个人博客
www.tothefor.com
蓝桥杯复习知识点汇总

目录

图的存储方式这里介绍三种:邻接矩阵、临接表、链式前向星。

邻接矩阵

这是最简单的,就是用二维数组实现。例如:G[a][b] = c;表示 a 点到 b 点之间的边的权重为 c 。

示例:

package acmtest;

import java.io.*;
import java.util.*;


/**
 * @Author DragonOne
 * @Date 2021/12/11 07:13
 * @墨水记忆 www.tothefor.com
 */

public class Main {
	public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
    public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
    public static Scanner sc = new Scanner(System.in);
    
    public static int maxd = 1000+7;
    
	public static void main(String[] args) throws Exception {
		
		int[][] G = new int[maxd][maxd];
		int n = nextInt(); //n个点
		int m = nextInt(); //m条边
		while(m-->0) {
			int a = nextInt(); //a点(起点)
			int b = nextInt(); //b点(终点)
			int c = nextInt(); //边的权重
			
			//有向图
//			G[a][b] = c; //a->b
			
			// 无向图
			G[a][b] = c; //a->b
			G[b][a] = c; //b->a
			
		}
		for(int i=1;i<=n;++i) {
			for(int j=1;j<=n;++j) {
				System.out.print(G[i][j]);
			}
			System.out.println();
		}
		
		
		closeAll();
		
	}


	public static int nextInt() throws Exception{
        cin.nextToken();
        return (int) cin.nval;
    }
    public static long nextLong() throws Exception{
        cin.nextToken();
        return (long) cin.nval;
    }
    public static double nextDouble() throws Exception{
        cin.nextToken();
        return cin.nval;
    }
    public static String nextString() throws Exception{
        cin.nextToken();
        return cin.sval;
    }
    public static void closeAll() throws Exception {
        cout.close();
        in.close();
        out.close();
    }
}


//样例
4 4
1 2 7
1 3 7
2 4 7
1 3 7
    
//输出
0770
7007
7000
0700

临接表

在C++中有一个STL容器叫作Vector,Java中也有,因为是线程安全的,所以效率低。而且也已经被弃用了。

Vector实现(不推荐,知道即可)

package acmtest;

import java.io.*;
import java.util.*;


/**
 * @Author DragonOne
 * @Date 2021/12/11 07:13
 * @墨水记忆 www.tothefor.com
 */

public class Main {
	public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
    public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
    public static Scanner sc = new Scanner(System.in);
    
    public static int maxd = 1000+7;
    
	public static void main(String[] args) throws Exception {
		int n = nextInt(); //n个点
		int m = nextInt(); //m条边
		Vector<Integer>[] v = new Vector[maxd];
		for(int i=1;i<=n;++i) {
			v[i]= new Vector<>(); 
		}
		while(m-->0) {
			int a = nextInt(); //a点(起点)
			int b = nextInt(); //b点(终点)
			v[a].add(b);
			v[b].add(a);
		}
		for(int i=1;i<=n;++i) {
			int len = v[i].size();
			System.out.print(i+" ");
			for(int j=0;j<len;++j) {
				System.out.print("-> "+v[i].get(j));
			}
			System.out.println();
		}
		
		closeAll();
		
	}
	
	public static int nextInt() throws Exception{
        cin.nextToken();
        return (int) cin.nval;
    }
    public static long nextLong() throws Exception{
        cin.nextToken();
        return (long) cin.nval;
    }
    public static double nextDouble() throws Exception{
        cin.nextToken();
        return cin.nval;
    }
    public static String nextString() throws Exception{
        cin.nextToken();
        return cin.sval;
    }
    public static void closeAll() throws Exception {
        cout.close();
        in.close();
        out.close();
    }
}


//样例
4 4
1 4
1 2
2 4
2 3

//输出
1 -> 4-> 2
2 -> 1-> 4-> 3
3 -> 2
4 -> 1-> 2

ArrayList实现

package acmtest;

import java.io.*;
import java.util.*;



/**
 * @Author DragonOne
 * @Date 2021/12/11 07:13
 * @墨水记忆 www.tothefor.com
 */

public class Main {
	public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
    public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
    public static Scanner sc = new Scanner(System.in);
    
    public static int maxd = 1000+7;
    
	public static void main(String[] args) throws Exception {
		int n = nextInt(); //n个点
		int m = nextInt(); //m条边
		ArrayList[] list = new ArrayList[maxd];
		for(int i=1;i<=n;++i) {
			list[i]= new ArrayList<Integer>();
		}
		while(m-->0) {
			int a = nextInt(); //a点(起点)
			int b = nextInt(); //b点(终点)
			list[a].add(b);
			list[b].add(a);
		}
		for(int i=1;i<=n;++i) {
			int len = list[i].size();
			System.out.print(i+" ");
			for(int j=0;j<len;++j) {
				System.out.print(" -> "+list[i].get(j));
			}
			System.out.println();
		}
		
		closeAll();
		
	}
	


	public static int nextInt() throws Exception{
        cin.nextToken();
        return (int) cin.nval;
    }
    public static long nextLong() throws Exception{
        cin.nextToken();
        return (long) cin.nval;
    }
    public static double nextDouble() throws Exception{
        cin.nextToken();
        return cin.nval;
    }
    public static String nextString() throws Exception{
        cin.nextToken();
        return cin.sval;
    }
    public static void closeAll() throws Exception {
        cout.close();
        in.close();
        out.close();
    }
}

//样例
4 4
1 4
1 3
2 3
2 4

//输出
1  -> 4 -> 3
2  -> 3 -> 4
3  -> 1 -> 2
4  -> 1 -> 2

LinkedList实现

同ArrayList实现一样的道理。只是把ArrayList改成LinkedList即可。不再演示。

链式前向星

实现的效果同临接表一样(存储方式也可以理解成临接表)。只不过是通过数组实现的。

用不同的方式实现链式前向星,本质一样,只是在增加边信息(add_edge()方法)的实现方式不同。

方式一(Setter/Getter方法)

package acmtest;

import java.io.*;
import java.util.*;



/**
 * @Author DragonOne
 * @Date 2021/12/11 07:13
 * @墨水记忆 www.tothefor.com
 */

public class Main {
	public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
    public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
    public static Scanner sc = new Scanner(System.in);
    
    public static int maxd = 1000+7;
    
    public static class Edge{
    	 private int pre; // pre表示与这条边同起点的上一条边所在结点的编号
    	 private int to; // to表示这条边的终点
    	 private int w; //表示边的权重
  
		public int getPre() {
			return pre;
		}
		public void setPre(int pre) {
			this.pre = pre;
		}
		public int getTo() {
			return to;
		}
		public void setTo(int to) {
			this.to = to;
		}
		public int getW() {
			return w;
		}
		public void setW(int w) {
			this.w = w;
		}
		
    }
    
    public static int node; //边的编号
    public static int[] head = new int[maxd]; //点集 head[i]表示以i为起点的最后一条边所在结点的编号
    public static Edge[] edge = new Edge[maxd]; //存储边信息
    //初始化
    public static void init() {
    	Arrays.fill(head, -1); //-1表示没有边
    	node = 0;
    }
    //增加边信息,a点到b点的边权重为w
    public static void add_edge(int a,int b,int w) {
    	edge[node]= new Edge(); //来一个声明一个
    	edge[node].setTo(b);
    	edge[node].setW(w);
    	edge[node].setPre(head[a]);
    	head[a]=node++;
    }
    
	public static void main(String[] args) throws Exception {
		int n = nextInt(); //n个点
		int m = nextInt(); //m条边
		init();
		while(m-->0) {
			int a = nextInt(); //a点(起点)
			int b = nextInt(); //b点(终点)
			int c = nextInt(); //边的权重
			//有向图
//			add_edge(a, b, c); //a->b
			
			//无向图
			add_edge(a, b, c); //a->b
			add_edge(b, a, c); //b->a
		}
		for(int i=1;i<=n;++i) {
			System.out.print(i+" ");
			for(int j=head[i];j!=-1;j=edge[j].getPre()) { //不断寻找当前点的上一条边,没有边(为-1时)则结束
				System.out.print(" -> "+edge[j].getTo());
			}
			System.out.println();
		}
		
		closeAll();
		
	}
	

	public static int nextInt() throws Exception{
        cin.nextToken();
        return (int) cin.nval;
    }
    public static long nextLong() throws Exception{
        cin.nextToken();
        return (long) cin.nval;
    }
    public static double nextDouble() throws Exception{
        cin.nextToken();
        return cin.nval;
    }
    public static String nextString() throws Exception{
        cin.nextToken();
        return cin.sval;
    }
    public static void closeAll() throws Exception {
        cout.close();
        in.close();
        out.close();
    }
}


//样例
4 4
1 4 7
1 3 7
2 4 7
3 4 7
    
//输出
1  -> 3 -> 4
2  -> 4
3  -> 4 -> 1
4  -> 3 -> 2 -> 1

此方式还有一种实现方法,在init()方法中进行,上面的代码是在增加一条边的时候才声明一条边,现在就可以一次性把需要的边声明完。只是在声明的时候需要注意是无向图还是有向图。(边数相差两倍

package acmtest;

import java.io.*;
import java.util.*;



/**
 * @Author DragonOne
 * @Date 2021/12/11 07:13
 * @墨水记忆 www.tothefor.com
 */

public class Main {
	public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
    public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
    public static Scanner sc = new Scanner(System.in);
    
    public static int maxd = 1000+7;
    
    public static class Edge{
    	 private int pre; // pre表示与这条边同起点的上一条边所在结点的编号
    	 private int to; // to表示这条边的终点
    	 private int w; //表示边的权重
  
		public int getPre() {
			return pre;
		}
		public void setPre(int pre) {
			this.pre = pre;
		}
		public int getTo() {
			return to;
		}
		public void setTo(int to) {
			this.to = to;
		}
		public int getW() {
			return w;
		}
		public void setW(int w) {
			this.w = w;
		}
		
    	 
    }
    public static int node; //边的编号
    public static int[] head = new int[maxd]; //点集 head[i]表示以i为起点的最后一条边所在结点的编号
    public static Edge[] edge = new Edge[maxd]; //存储边信息
    //初始化
    public static void init(int m) {
    	Arrays.fill(head, -1); //-1表示没有边
    	for(int i=0;i<=m*2;++i) { //这里是无向图,所以边数要乘2。必须要从0开始,因为边的编号是从0开始的,即node是从0开始的
    		edge[i] = new Edge();
    	}
    	node = 0;
    }
    //增加边信息,a点到b点的边权重为w
    public static void add_edge(int a,int b,int w) {
    	edge[node].setTo(b);
    	edge[node].setW(w);
    	edge[node].setPre(head[a]);
    	head[a]=node++;
    }
    
	public static void main(String[] args) throws Exception {
		int n = nextInt(); //n个点
		int m = nextInt(); //m条边
		init(m);
		while(m-->0) {
			int a = nextInt(); //a点(起点)
			int b = nextInt(); //b点(终点)
			int c = nextInt(); //边的权重
			//有向图
//			add_edge(a, b, c); //a->b
			
			//无向图
			add_edge(a, b, c); //a->b
			add_edge(b, a, c); //b->a
		}
		for(int i=1;i<=n;++i) {
			System.out.print(i+" ");
			for(int j=head[i];j!=-1;j=edge[j].getPre()) { //不断寻找当前点的上一条边,没有边(为-1时)则结束
				System.out.print(" -> "+edge[j].getTo());
			}
			System.out.println();
		}
		
		closeAll();
		
	}
	

	public static int nextInt() throws Exception{
        cin.nextToken();
        return (int) cin.nval;
    }
    public static long nextLong() throws Exception{
        cin.nextToken();
        return (long) cin.nval;
    }
    public static double nextDouble() throws Exception{
        cin.nextToken();
        return cin.nval;
    }
    public static String nextString() throws Exception{
        cin.nextToken();
        return cin.sval;
    }
    public static void closeAll() throws Exception {
        cout.close();
        in.close();
        out.close();
    }
}

方式二(构造函数)

package acmtest;

import java.io.*;
import java.util.*;



/**
 * @Author DragonOne
 * @Date 2021/12/11 07:13
 * @墨水记忆 www.tothefor.com
 */

public class Main {
	public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
    public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
    public static Scanner sc = new Scanner(System.in);
    
    public static int maxd = 1000+7;
    
    public static class Edge{
    	 private int pre; // pre表示与这条边同起点的上一条边所在结点的编号
    	 private int to; // to表示这条边的终点
    	 private int w; //表示边的权重
    	 
    	public Edge() {}
    	public Edge(int pre,int to,int w) {
			this.pre= pre;
			this.to= to;
			this.w= w;
		}
		public int getPre() {
			return pre;
		}
		public void setPre(int pre) {
			this.pre = pre;
		}
		public int getTo() {
			return to;
		}
		public void setTo(int to) {
			this.to = to;
		}
		public int getW() {
			return w;
		}
		public void setW(int w) {
			this.w = w;
		}
		
    	 
    }
    public static int node; //边的编号
    public static int[] head = new int[maxd]; //点集 head[i]表示以i为起点的最后一条边所在结点的编号
    public static Edge[] edge = new Edge[maxd]; //存储边信息
    //初始化
    public static void init() {
    	Arrays.fill(head, -1); //-1表示没有边
    	node = 0;
    }
    //增加边信息,a点到b点的边权重为w
    public static void add_edge(int a,int b,int w) {
    	edge[node]= new Edge(head[a],b,w); 
    	head[a]=node++;
    }
    
	public static void main(String[] args) throws Exception {
		int n = nextInt(); //n个点
		int m = nextInt(); //m条边
		init();
		while(m-->0) {
			int a = nextInt(); //a点(起点)
			int b = nextInt(); //b点(终点)
			int c = nextInt(); //边的权重
			//有向图
//			add_edge(a, b, c); //a->b
			
			//无向图
			add_edge(a, b, c); //a->b
			add_edge(b, a, c); //b->a
		}
		for(int i=1;i<=n;++i) {
			System.out.print(i+" ");
			for(int j=head[i];j!=-1;j=edge[j].getPre()) { //不断寻找当前点的上一条边,没有边(为-1时)则结束
				System.out.print(" -> "+edge[j].getTo());
			}
			System.out.println();
		}
		
		closeAll();
		
	}
	

	public static int nextInt() throws Exception{
        cin.nextToken();
        return (int) cin.nval;
    }
    public static long nextLong() throws Exception{
        cin.nextToken();
        return (long) cin.nval;
    }
    public static double nextDouble() throws Exception{
        cin.nextToken();
        return cin.nval;
    }
    public static String nextString() throws Exception{
        cin.nextToken();
        return cin.sval;
    }
    public static void closeAll() throws Exception {
        cout.close();
        in.close();
        out.close();
    }
}

//样例
4 4
1 4 7
1 3 7
2 4 7
3 4 7
    
//输出
1  -> 3 -> 4
2  -> 4
3  -> 4 -> 1
4  -> 3 -> 2 -> 1
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值