一、无向图的几种数据结构
我们要面对的下一个图处理问题就是用哪种方式(数据结构)来表示图并实现这份 API,这包含以下两个要求:
- 它必须为可能在应用中碰到的各种类型图预留足够的空间;
- 实现一定要块
- 邻接矩阵:我们可以使用V乘V的布尔矩阵。当顶点v和顶点w之间有相连接边时,定义v 行w列的元素为true,否则为false。当含有上百万个顶点的图是很常见的,
个布尔值所需的空间是不能满足的。其次大部分图都是稀疏的,所以用邻接矩阵表示浪费空间。
- 邻接表:我们可以使用一个以顶点为索引的列表数组,其中的每个元素都是和该顶点相邻的顶点列表。这种数据结构能够同时满足以上的两个条件,所以我准备用java实现这种结构。
二、api定义
Graph | ||
public Graph() | 无参构造函数 | |
public Graph(int vertices) | 有参构造函数,vertices为顶点数 | |
public void createGraphByFile(String path) | 根据文件创建图,path为文件路径 | |
public void addEdge(int v,int w) | 添加一条边,v和w是顶点编号 | |
public Collection<Integer> adj(int v) | 返回与v相邻的所有顶点列表 | |
public int getVertices() | 返回顶点数 | |
public int getEdges() | 返回边数 | |
public String toString() | 打印邻接表 |
三、代码实现
package graph;
import java.io.*;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
/**
* 使用邻接表实现图算法
* @author hh
*/
public class Graph {
/**
* 顶点数
*/
private int vertices;
/**
* 边数
*/
private int edges;
/**
* 邻接表
*/
private List<Integer>[] adj;
public Graph() {
}
public Graph(int vertices) {
this.init(vertices);
}
/**
* 从文件中创建图
* @param path :文件路径
*/
public void createGraphByFile(String path) throws Exception{
try (BufferedReader bufferedReader = new BufferedReader(new FileReader(new File(path)))) {
int vs = Integer.parseInt(bufferedReader.readLine().trim());
int es = Integer.parseInt(bufferedReader.readLine().trim());
if(vs <= 0){
throw new IllegalArgumentException("顶点数量必须大于0!");
}
if(es < 0){
throw new IllegalArgumentException("边的数量必须大于等于0!");
}
init(vs);
for(int i = 0 ; i < es ; i++){
String[] vl = bufferedReader.readLine().trim().split(" ");
this.addEdge(Integer.parseInt(vl[0].trim()),Integer.parseInt(vl[1].trim()));
}
} catch (Exception e){
e.printStackTrace();
}
}
/**
* 添加一条边
* @param v :顶点v编号
* @param w :顶点w编号
*/
public void addEdge(int v,int w){
this.adj[v].add(w);
this.adj[w].add(v);
this.edges++;
}
/**
* 返回与v相邻的所有顶点列表
* @param v :顶点编号
* @return :返回与v相邻的所有顶点列表
*/
public Collection<Integer> adj(int v){
return adj[v];
}
/**
* @return :返回顶点数
*/
public int getVertices() {
return vertices;
}
/**
* @return ;返回边数
*/
public int getEdges() {
return edges;
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder(this.edges*this.vertices);
for(int i=0 ; i < this.vertices ;i++){
stringBuilder.append(i).append("->").append(adj[i]).append("\n");
}
return stringBuilder.toString();
}
private void init(int vertices){
this.vertices = vertices;
//初始化邻接表
this.adj = new LinkedList[vertices];
for(int i = 0;i < vertices; i++){
this.adj[i] = new LinkedList<>();
}
}
}
测试从文件创建图,文件定义格式如下:
测试代码如下:
public class GraphTest {
public static void main(String[] args) throws Exception {
String filename = "D:\\Desktop\\graph.txt";
Graph graph = new Graph();
graph.createGraphByFile(filename);
System.out.println(graph);
}
}
执行结果如下: