图是一种较为复杂的数据结构,并且在地理信息系统,游戏等领域的开发中的应用非常广泛。但其实现起来较为复杂,故将图常用的实现方式和图操作的基本方法封装了起来以求作为基础,并在基础之上拓展延伸出图的更为复杂的操作,由于时间有限,只有有向图的实现,而无向图需要对其中的某些代码加以增加,另外算法功力着实有限,并不能保证所有算法均为最优,在邻接矩阵的实现 中添加了当超出数量上限时自动扩大数组范围的功能,但不能保证这对性能的影响是最小的。发布出来 全且当作与大家共同学习探讨的媒介,望各位大侠不吝赐教。
1.图通用类的接口的设计:
package com.dk.javaSTL;
import java.util.ArrayList;
public interface GraphSet<T> {
public static final byte unDigraph = 0;//无向图标志
public static final byte Digraph = 1;//有向图标志
public static final byte Matrix = 0;//邻接矩阵实现
public static final byte AdjList = 1;//邻接表实现
public boolean isNULLGraph() throws Exception; //判断为空的方法
public void MakeNULLGraph();//图置空
public GraphNode<T> firstVertex();//获得图的首节点
public ArrayList<GraphNode<T>> nextVertex(GraphNode<T> node);//获得已知节点的下一个节点
public ArrayList<GraphNode<T>> searchVertex(int[] val, int count);//搜索节点
public boolean addVertex(T val);//添加顶点
public boolean deleteVertex(int num);//删除定点
public boolean addEdge(int vnum1, int vnum2);//两点之间添加弧 参数为定点标号
public boolean deleteEdge(int vnum1, int vnum2);//删除两点之间的弧
public boolean EdgeExists(int vnum1, int vnum2);//判断两点之间的弧是否存在
}
2.顶点 以及 弧 的数据结构
package com.dk.javaSTL;
public class GraphNode<T> {
private int num;
private T data;
private GraphEdge edgeList;
private GraphNode<T> nextVertex;
public GraphNode(int num, T data) {
this.setNum(num);
this.setData(data);
this.setEdgeList(null);
this.setNextVertex(null);
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public GraphEdge getEdgeList() {
return edgeList;
}
public void setEdgeList(GraphEdge edgeList) {
this.edgeList = edgeList;
}
public GraphNode<T> getNextVertex() {
return nextVertex;
}
public void setNextVertex(GraphNode<T> nextVertex) {
this.nextVertex = nextVertex;
}
}
package com.dk.javaSTL;
public class GraphEdge {
private int endvex;
private int weight;
private GraphEdge nextEdge;
public GraphEdge(int ev, int weight, GraphEdge next) {
this.setEndvex(ev);
this.setWeight(weight);
this.setNextEdge(next);
}
public int getEndvex() {
return endvex;
}
public void setEndvex(int endvex) {
this.endvex = endvex;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public GraphEdge getNextEdge() {
return nextEdge;
}
public void setNextEdge(GraphEdge nextEdge) {
this.nextEdge = nextEdge;
}
}
3.Graph通用类实现
package com.dk.javaSTL;
import java.util.ArrayList;
public class Graph<T> implements GraphSet<T> {
private byte directionType;
private byte Method;
private int VertexSize;
private int MatrixMaxVertex;
private GraphNode<T>[] Vertexs;
private int[][] EdgesMatrix;
private int[] temp;
private GraphNode<T> headptr;
private GraphNode<T> tailptr;
public byte getDirectionType() {
return directionType;
}
public void setDirectionType(byte directionType) {
this.directionType = directionType;
}
public byte getMethod() {
return Method;
}
public void setMethod(byte method) {
Method = method;
}
public int getVertexSize() {
return VertexSize;
}
public void setVertexSize(int i) {
this.VertexSize = i;
}
public GraphNode<T> getHeadptr() {
return headptr;
}
public void setHeadptr(GraphNode<T> headptr) {
this.headptr = headptr;
}
public GraphNode<T>[] getVertexs() {
return Vertexs;
}
public void setVertexs(GraphNode<T>[] vertex) {
Vertexs = vertex;
}
public int[][] getEdgesMatrix() {
return EdgesMatrix;
}
public void setEdgesMatrix(int[][] edges) {
EdgesMatrix = edges;
}
public int getMatrixMaxVertex() {
return MatrixMaxVertex;
}
public void setMatrixMaxVertex(int matrixMaxVertex) {
MatrixMaxVertex = matrixMaxVertex;
}
public int[] getTemp() {
return temp;
}
public void setTemp(int[] temp) {
this.temp = temp;
}
public GraphNode<T> getTailptr() {
return tailptr;
}
public void setTailptr(GraphNode<T> tailptr) {
this.tailptr = tailptr;
}
public Graph(byte dtype, byte method) {
this.setDirectionType(dtype);
this.setMethod(method);
this.setVertexSize(0);
this.setHeadptr(null);
this.setTailptr(null);
if (method == GraphSet.Matrix) {
Vertexs = new GraphNode[this.getMatrixMaxVertex()];
EdgesMatrix = new int[this.getMatrixMaxVertex()][this
.getMatrixMaxVertex()];
}
}
public Graph(byte dtype, byte method, int size) {
this.setDirectionType(dtype);
this.setMethod(method);
this.setVertexSize(0);
this.setMatrixMaxVertex(size);
this.setHeadptr(null);
this.setTailptr(null);
if (method == GraphSet.Matrix) {
Vertexs = new GraphNode[this.getMatrixMaxVertex()];
EdgesMatrix = new int[this.getMatrixMaxVertex()][this
.getMatrixMaxVertex()];
}
}
// ok
@Override
public boolean isNULLGraph() throws Exception {
if (this.getVertexSize() == 0 || this.getHeadptr() == null)
return true;
return false;
}
// ok
@Override
public void MakeNULLGraph() {
this.setHeadptr(null);
this.setVertexSize(0);
this.setVertexs(null);
Runtime.getRuntime().gc();
}
// ok
@Override
public GraphNode<T> firstVertex() {
if (this.getMethod() == GraphSet.Matrix)
return this.getVertexs()[0];
else if (this.getMethod() == GraphSet.AdjList)
return this.getHeadptr();
return null;
}
// ok
@Override
public ArrayList<GraphNode<T>> nextVertex(GraphNode<T> node) {
assert (node != null);
int count = 0;
temp = new int[this.getVertexSize()];
for (int i = 0; i < this.VertexSize; i++)
this.temp[i] = -1;
ArrayList<GraphNode<T>> Sequence = null;
if (this.getMethod() == GraphSet.Matrix) {
int index = node.getNum();
for (int i = 0; i < this.getEdgesMatrix()[index].length; i++)
if (this.getEdgesMatrix()[index][i] != 0)
temp[count++] = i;
} else if (this.getMethod() == GraphSet.AdjList) {
GraphEdge edge = node.getEdgeList();
assert (edge != null);
while (edge != null) {
temp[count++] = edge.getEndvex();
edge = edge.getNextEdge();
}
} else
return null;
Sequence = this.searchVertex(temp, count);
return Sequence;
}
// ok
@Override
public ArrayList<GraphNode<T>> searchVertex(int[] val, int count) {
assert (val != null);
if (count == 0)
return null;
ArrayList<GraphNode<T>> Sequence = new ArrayList<GraphNode<T>>();
if (this.getMethod() == GraphSet.Matrix) {
GraphNode<T>[] node = this.getVertexs();
for (int i = 0; i < this.getVertexs().length; i++)
for (int j = 0; j < val.length; j++)
if (node[i].getNum() == val[j])
Sequence.add(node[i]);
} else if (this.getMethod() == GraphSet.AdjList) {
GraphNode<T> node = this.getHeadptr();
while (node != null) {
for (int i = 0; i < val.length; i++)
if (node.getNum() == val[i])
Sequence.add(node);
node = node.getNextVertex();
}
} else
return null;
return Sequence;
}
// ok
@Override
public boolean addVertex(T val) {
assert (val != null);
if (this.getMethod() == GraphSet.Matrix) {
if (this.getVertexSize() == this.getMatrixMaxVertex()) {
int count = 0;
GraphNode<T>[] vsource = this.getVertexs();
GraphNode<T>[] vtarget = new GraphNode[this.MatrixMaxVertex *= 2];
int[][] esource = this.getEdgesMatrix();
int[][] etarget = new int[this.getMatrixMaxVertex()][this
.getMatrixMaxVertex()];// noted
while (count < this.VertexSize) {
vtarget[count] = vsource[count];
count++;
}
vtarget[count] = new GraphNode<T>(this.VertexSize++, val);
for (int i = 0; i < this.VertexSize; i++)
for (int j = 0; j < this.VertexSize; j++)
if (i == this.VertexSize - 1
|| j == this.VertexSize - 1)
etarget[i][j] = 0;
this.setVertexs(vtarget);
this.setEdgesMatrix(etarget);
Runtime.getRuntime().gc();
} else
this.getVertexs()[this.VertexSize] = new GraphNode<T>(
this.VertexSize++, val);
} else if (this.getMethod() == GraphSet.AdjList) {
GraphNode<T> workptr = new GraphNode<T>(this.VertexSize, val);
if (this.VertexSize == 0)
this.headptr = workptr;
else
this.tailptr.setNextVertex(workptr);
this.tailptr = workptr;
this.VertexSize++;
} else
return false;
return true;
}
// ok
@Override
public boolean deleteVertex(int num) {
assert (num >= 0);
if (this.VertexSize == 0)
return false;
if (this.getMethod() == GraphSet.Matrix) {
int index = -1;
for (int i = 0; i < this.VertexSize; i++)
if (this.getVertexs()[i].getNum() == num) {
index = i;
break;
}
if (index == -1)
return false;
for (int i = index; i < this.VertexSize-1; i++)
this.Vertexs[i] = this.Vertexs[i+1];
for (int i = index; i < this.VertexSize-1; i++)
for (int j = 0; j < this.VertexSize; j++)
this.EdgesMatrix[i][j] = this.EdgesMatrix[i+1][j];
for (int i = 0; i < this.VertexSize; i++)
for (int j = index; j < this.VertexSize-1; j++)
this.EdgesMatrix[i][j] = this.EdgesMatrix[i][j+1];
this.Vertexs[this.VertexSize - 1] = null;
Runtime.getRuntime().gc();
} else if (this.getMethod() == GraphSet.AdjList) {
if (this.headptr.getNum() == num) {
this.headptr = this.headptr.getNextVertex();
this.VertexSize--;
return true;
}
GraphNode<T> workptr = this.getHeadptr();
GraphNode<T> helpptr = this.getHeadptr();
while (workptr != null) {
if (workptr.getNum() == num)
break;
helpptr = workptr;
workptr = workptr.getNextVertex();
}
if (workptr == null)
return false;
helpptr.setNextVertex(workptr.getNextVertex());
workptr.setNextVertex(null);
Runtime.getRuntime().gc();
} else
return false;
this.VertexSize--;
return true;
}
// ok
@Override
public boolean addEdge(int vnum1, int vnum2) {
assert (vnum1 > 0 && vnum2 > 0 && vnum1 != vnum2);
if (this.getMethod() == GraphSet.Matrix)
this.EdgesMatrix[vnum1][vnum2] = 1;
else if (this.getMethod() == GraphSet.AdjList) {
GraphNode<T> workptr1 = this.headptr;
while (workptr1 != null)
if (workptr1.getNum() == vnum1) {
if (workptr1.getEdgeList() == null) {
workptr1.setEdgeList(new GraphEdge(vnum2, 1, null));
return true;
}
GraphEdge workptr2 = workptr1.getEdgeList();
while (workptr2.getNextEdge() != null)
workptr2 = workptr2.getNextEdge();
workptr2.setNextEdge(new GraphEdge(vnum2, 1, null));
break;
} else
workptr1 = workptr1.getNextVertex();
} else
return false;
return true;
}
// ok
@Override
public boolean deleteEdge(int vnum1, int vnum2) {
assert (vnum1 > 0 && vnum2 > 0 && vnum1 != vnum2);
if (this.getMethod() == GraphSet.Matrix)
this.EdgesMatrix[vnum1][vnum2] = 0;
else if (this.getMethod() == GraphSet.AdjList) {
GraphNode<T> workptr = this.headptr;
while (workptr != null)
if (workptr.getNum() == vnum1) {
if (workptr.getEdgeList().getEndvex() == vnum2) {
workptr.setEdgeList(workptr.getEdgeList().getNextEdge());
break;
}
GraphEdge workptr1 = workptr.getEdgeList();
GraphEdge workptr2 = workptr.getEdgeList();
while (workptr1.getEndvex() != vnum2) {
workptr2 = workptr1;
workptr1 = workptr1.getNextEdge();
}
workptr2.setNextEdge(workptr1.getNextEdge());
workptr1.setNextEdge(null);
break;
} else
workptr = workptr.getNextVertex();
} else
return false;
Runtime.getRuntime().gc();
return true;
}
// ok
@Override
public boolean EdgeExists(int vnum1, int vnum2) {
assert (vnum1 >= 0 && vnum2 >= 0 && vnum1 != vnum2);
if (this.getMethod() == GraphSet.Matrix)
return (this.getEdgesMatrix()[vnum1][vnum2] == 0 ? false : true);
else if (this.getMethod() == GraphSet.AdjList) {
GraphNode<T> workptr = this.headptr;
while (workptr != null) {
if (workptr.getNum() == vnum1) {
GraphEdge workptr1 = workptr.getEdgeList();
while (workptr1 != null)
if (workptr1.getEndvex() == vnum2)
return true;
else
workptr1 = workptr1.getNextEdge();
}
workptr = workptr.getNextVertex();
}
} else
return false;
return false;
}
}