注意:抽象类实现某个接口时,可以不实现接口的所有方法,由它的子类来实现,但是普通类即非抽象类则必须实现接口里的所有方法。
/**
*
*/
package com.sunlei;
import java.util.List;
/**
*@author 作者:sunlei
*@version 创建时间:2018年2月27日下午6:47:54
*说明
*/
public interface Graph<T> {
//返回图中的顶点数
public int getSize();
//返回图的顶点
public List<T> getVertices();
//返回指定下标的顶点对象
public T getVertex(int index);
//返回指定定点的下标
public int getIndex(T v);
//返回指定下标的顶点的邻居
public List<Integer> getNeighbors(int index);
//返回指点定点下标的度
public int getDegree(int v);
//打印边
public void printEdges();
//清除图
public void clear();
//添加定点
public boolean addVertex(T vertex);
//添加边
public boolean addEdge(int u,int v);
//从顶点v开始一个深度优先搜索树
public AbstractGraph<T>.Tree dfs(int v);
//从顶点v开始一个广度优先搜索树
public AbstractGraph<T>.Tree bfs(int v);
}
/**
*
*/
package com.sunlei;
import java.util.ArrayList;
import java.util.List;
/**
*@author 作者:sunlei
*@version 创建时间:2018年2月27日下午6:59:31
*说明
*/
public class AbstractGraph<T> implements Graph<T> {
protected List<T> vertices = new ArrayList<>(); //图中的顶点
protected List<List<Edge>> neighbors = new ArrayList<>(); //图中每个顶点的邻居
//创建一个空图
protected AbstractGraph() {
}
//从存储在数组中的指定边和顶点构建一个图
protected AbstractGraph(T[] vertices,int[][] edges) {
for(int i=0;i<vertices.length;i++) {
addVertex(vertices[i]);
}
createAdjacencyLists(edges,vertices.length);
}
//从存储在线性表中的指定边和顶点构建一个图
protected AbstractGraph(List<T> vertices,List<Edge> edges) {
for(int i=0;i<vertices.size();i++) {
addVertex(vertices.get(i));
}
createAdjacencyLists(edges,vertices.size());
}
protected AbstractGraph(List<Edge> edges,int numberOfVertices) {
for(int i=0;i<numberOfVertices;i++) {
addVertex((T)(new Integer(i)));
}
createAdjacencyLists(edges,numberOfVertices);
}
protected AbstractGraph(int[][] edges,int numberOfVertices) {
for(int i=0;i<numberOfVertices;i++) {
addVertex((T)(new Integer(i)));
}
createAdjacencyLists(edges,numberOfVertices);
}
private void createAdjacencyLists(int[][] edges,int numberOfVertices) {
for(int i=0;i<edges.length;i++) {
addEdge(edges[i][0],edges[i][1]);
}
}
private void createAdjacencyLists(List<Edge> edges,int numberOfVertices) {
for(Edge edge:edges) {
addEdge(edge.u,edge.v);
}
}
/* (non-Javadoc)
* @see com.sunlei.Graph#getSize()
*/
@Override
public int getSize() {
// TODO Auto-generated method stub
return vertices.size();
}
/* (non-Javadoc)
* @see com.sunlei.Graph#getVertices()
*/
@Override
public List<T> getVertices() {
// TODO Auto-generated method stub
return vertices;
}
/* (non-Javadoc)
* @see com.sunlei.Graph#getVertex(int)
*/
@Override
public T getVertex(int index) {
// TODO Auto-generated method stub
return vertices.get(index);
}
/* (non-Javadoc)
* @see com.sunlei.Graph#getIndex(java.lang.Object)
*/
@Override
public int getIndex(T v) {
// TODO Auto-generated method stub
return vertices.indexOf(v);
}
/* (non-Javadoc)
* @see com.sunlei.Graph#getNeighbors(int)
*/
@Override
public List<Integer> getNeighbors(int index) {
// TODO Auto-generated method stub
List<Integer> result = new ArrayList<>();
for(Edge e:neighbors.get(index))
result.add(e.v);
return result;
}
/* (non-Javadoc)
* @see com.sunlei.Graph#getDegree(int)
*/
@Override
public int getDegree(int v) {
// TODO Auto-generated method stub
return neighbors.get(v).size();
}
/* (non-Javadoc)
* @see com.sunlei.Graph#printEdges()
*/
@Override
public void printEdges() {
// TODO Auto-generated method stub
for(int i=0;i<neighbors.size();i++) {
System.out.print(getVertex(i) + "(" + i + "):");
for(Edge e:neighbors.get(i)){
System.out.print("(" + getVertex(e.u) + "," + getVertex(e.v) + ")");
}
System.out.println();
}
}
/* (non-Javadoc)
* @see com.sunlei.Graph#clear()
*/
@Override
public void clear() {
// TODO Auto-generated method stub
vertices.clear();
neighbors.clear();
}
/* (non-Javadoc)
* @see com.sunlei.Graph#addVertex(java.lang.Object)
*/
@Override
public boolean addVertex(T vertex) {
// TODO Auto-generated method stub
if(!vertices.contains(vertex)) {
vertices.add(vertex);
neighbors.add(new ArrayList<Edge>());
return true;
}
else {
return false;
}
}
protected boolean addEdge(Edge e) {
if(e.u < 0 || e.u > getSize() - 1) {
throw new IllegalArgumentException("No such index:" + e.u);
}
if(e.v < 0 || e.v > getSize() - 1) {
throw new IllegalArgumentException("No such index:" + e.v);
}
if(!neighbors.get(e.u).contains(e)) {
neighbors.get(e.u).add(e);
return true;
}
else {
return false;
}
}
/* (non-Javadoc)
* @see com.sunlei.Graph#addEdge(int, int)
*/
@Override
public boolean addEdge(int u, int v) {
// TODO Auto-generated method stub
return addEdge(new Edge(u,v));
}
public static class Edge {
int u;
int v;
public Edge(int u,int v) {
this.u = u;
this.v = v;
}
public boolean equals(Object o) {
return u == ((Edge)o).u && v == ((Edge)o).v;
}
}
/* (non-Javadoc)
* @see com.sunlei.Graph#dfs(int)
*/
@Override
public AbstractGraph<T>.Tree dfs(int v) {
List<Integer> searchOrder = new ArrayList<>();
int[] parent = new int[vertices.size()];
for(int i=0;i<parent.length;i++) {
parent[i] = -1;
}
boolean[] isVisited = new boolean[vertices.size()];
dfs(v,parent,searchOrder,isVisited);
return new Tree(v,parent,searchOrder);
}
private void dfs(int u ,int[] parent,List<Integer> searchOrder,boolean[] isVisited) {
searchOrder.add(u);
isVisited[u] = true;
for(Edge e : neighbors.get(u)) {
if(!isVisited[e.u]) {
parent[e.v] = u;
dfs(e.v,parent,searchOrder,isVisited);
}
}
}
/* (non-Javadoc)
* @see com.sunlei.Graph#bfs(int)
*/
@Override
public AbstractGraph<T>.Tree bfs(int v) {
// TODO Auto-generated method stub
return null;
}
public class Tree {
private int root;
private int[] parent;
private List<Integer> searchOrder;
public Tree(int root ,int[] parent, List<Integer> searchOrder) {
this.root = root;
this.parent = parent;
this.searchOrder = searchOrder;
}
public int getRoot() {
return root;
}
public int getParent(int v) {
return parent[v];
}
public List<Integer> getSearchOrder(){
return searchOrder;
}
public int getNumberOfVerticesFound() {
return searchOrder.size();
}
public List<T> getPath(int index){
ArrayList<T> path = new ArrayList<>();
do {
path.add(vertices.get(index));
index = parent[index];
}
while(index != -1);
return path;
}
public void printPath(int index) {
List<T> path = getPath(index);
System.out.print("A path from " + vertices.get(root) + " to " + vertices.get(index) + ": ");
for(int i=path.size()-1;i>=0;i--) {
System.out.print(path.get(i) + " ");
}
}
public void printTree() {
System.out.println("Root is: " + vertices.get(root));
System.out.print("Edges: ");
for(int i=0;i<parent.length;i++) {
if(parent[i] != -1) {
System.out.print("(" + vertices.get(parent[i]) + "," + vertices.get(i) + ")");
}
}
System.out.println();
}
}
}
/**
*
*/
package com.sunlei;
import java.util.List;
/**
*@author 作者:sunlei
*@version 创建时间:2018年2月27日下午7:33:49
*说明
*/
public class UnweightedGraph<T> extends AbstractGraph<T> {
public UnweightedGraph() {
}
public UnweightedGraph(T[] vertices,int[][] edges) {
super(vertices,edges);
}
public UnweightedGraph(List<T> vertices,List<Edge> edges) {
super(vertices,edges);
}
public UnweightedGraph(List<Edge> edges,int numberOfVertices) {
super(edges,numberOfVertices);
}
public UnweightedGraph(int[][] edges,int numberOfVertices) {
super(edges,numberOfVertices);
}
}
/**
*
*/
package com.sunlei;
/**
*@author 作者:sunlei
*@version 创建时间:2018年2月27日下午6:37:54
*说明
*/
public class TestGraph {
/**
* @param args
*/
public static void main(String[] args) {
String[] vertices = {"Wuhan","Chengdu","Hefei","Nanjing","Beijing","Xiamen",
"Xiantao","Tianmen","Qianjing","Chongqing","Shanghai","Hangzhou"};
int[][] edges = {
{0,1},{0,3},{0,5},
{1,0},{1,2},{1,3},
{2,1},{2,2},{2,4},{2,10},
{3,0},{3,1},{3,2},{3,4},{3,5},
{4,2},{4,3},{4,5},{4,7},{4,8},{4,10},
{5,0},{5,3},{5,4},{5,6},{5,7},
{6,5},{6,7},
{7,4},{7,5},{7,6},{7,8},
{8,4},{8,7},{8,9},{8,10},{8,11},
{9,8},{9,11},
{10,2},{10,4},{10,8},{10,11},
{11,8},{11,9},{11,10}
};
Graph<String> graph1 = new UnweightedGraph<>(vertices,edges);
System.out.println("The number of vertices in graph1:" + graph1.getSize());
System.out.println("The vertex with index 1 is:" + graph1.getVertex(1));
System.out.println("The index for Xiantao in graph1:" + graph1.getIndex("Xiantao"));
System.out.println("The edges for graph1:" );
graph1.printEdges();
}
}