我正在开发一个邻接矩阵,所以我可以尝试使用DFS来解决euler电路问题。 这是我的问题的相关代码:
public class Graph {
private int numVertex;
private int numEdges;
private boolean[][] adj;
public Graph(int numVertex, int numEdges) {
this.numVertex = numVertex;
this.numEdges = numEdges;
this.adj = new boolean[numVertex][numVertex];
}
public void addEdge(int start, int end){
if(!adj[start][end])
numEdges++;
adj[start][end] = true;
adj[end][start] = true;
}
当我尝试通过添加一些边缘来测试运行此代码时,我得到:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
at Graph.addEdge(Graph.java:18)
at Graph.main(Graph.java:66)
我正在使用它来测试代码:
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int numVertices = input.nextInt();
int numLinks = input.nextInt();
int startNode = input.nextInt();
Graph g = new Graph(numVertices, numLinks);
for(int i = 0; i<numLinks; i++){
g.addEdge(input.nextInt(),input.nextInt());
}
我认为问题出在addEdge函数中。我做错了什么?
答案 0 :(得分:2)
请记住,您的矩阵是从零开始的。
如果您将4作为numVertices传递,则矩阵将从0,0变为3,3。
然后,如果您尝试在顶点4和任何其他顶点之间添加边缘,则会出现错误...
答案 1 :(得分:2)
当您增加边数时,adj
矩阵的大小不会自动更改。增长图形时,需要重新分配矩阵并将旧值复制到新矩阵。您可以通过分配一个更大的矩阵来开始(因此大小和容量之间存在差异)并且仅在容量耗尽时重新分配,从而节省重新分配。
我可以建议,因为你只是存储一个布尔值,而不是二维矩阵,你只需要使用BitSet
(它实际上是一个位向量,而不是一个集合)。您可以使用以下方法将(行,列)对转换为线性数组索引:
index = row * numEdges + column;
你可以用另一种方式(如果需要)用:
column = index % numEdges;
row = index / numEdges;
当图表增长时,您仍需要重新分配BitSet
,但您将节省大量存储空间。
修改强>
第二个想法,我认为问题是你没有检查顶点数是否在范围内。如果希望用户指定从1开始的顶点数,则需要从用户输入中减去1,以便adj
的索引从0开始。至少应检查端点输入是否有效
如果你想尝试一下,BitSet
实现看起来像这样:
public class Graph {
private int numVertex;
private int numEdges;
private BitSet adj;
public Graph(int numVertex, int numEdges) {
this.numVertex = numVertex;
this.numEdges = numEdges;
this.adj = new BitSet(numVertex * numVertex);
}
public void addEdge(int start, int end){
int index = start * numVertex + end;
if (!adj.get(index)) {
adj.set(index);
index = end * numVertex + start;
adj.set(index);
numEdges++;
}
}
由于邻接矩阵是对称的,因此只需存储上(或下)三角形部分即可节省更多存储空间。但这会使索引计算变得更复杂。