您好我正在尝试完成作业,可以咨询在线社区。我必须创建一个图表类,最终可以进行广度优先搜索和深度优先搜索。我已经能够成功地实现这些算法,但另一个要求是能够获得后继者和前任,并检测两个顶点是否是彼此的前驱或后继。我无法想办法做到这一点。我将在下面发布我的代码,如果有人有任何建议,将非常感谢。
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class Graph<T>
{
public Vertex<T> root;
public ArrayList<Vertex<T>> vertices=new ArrayList<Vertex<T>>();
public int[][] adjMatrix;
int size;
private ArrayList<Vertex<T>> dfsArrList;
private ArrayList<Vertex<T>> bfsArrList;
public void setRootVertex(Vertex<T> n)
{
this.root=n;
}
public Vertex<T> getRootVertex()
{
return this.root;
}
public void addVertex(Vertex<T> n)
{
vertices.add(n);
}
public void removeVertex(int loc){
vertices.remove(loc);
}
public void addEdge(Vertex<T> start,Vertex<T> end)
{
if(adjMatrix==null)
{
size=vertices.size();
adjMatrix=new int[size][size];
}
int startIndex=vertices.indexOf(start);
int endIndex=vertices.indexOf(end);
adjMatrix[startIndex][endIndex]=1;
adjMatrix[endIndex][startIndex]=1;
}
public void removeEdge(Vertex<T> v1, Vertex<T> v2){
int startIndex=vertices.indexOf(v1);
int endIndex=vertices.indexOf(v2);
adjMatrix[startIndex][endIndex]=1;
adjMatrix[endIndex][startIndex]=1;
}
public int countVertices(){
int ver = vertices.size();
return ver;
}
/*
public boolean isPredecessor( Vertex<T> a, Vertex<T> b){
for()
return true;
}*/
/*
public boolean isSuccessor( Vertex<T> a, Vertex<T> b){
for()
return true;
}*/
public void getSuccessors(Vertex<T> v1){
}
public void getPredessors(Vertex<T> v1){
}
private Vertex<T> getUnvisitedChildNode(Vertex<T> n)
{
int index=vertices.indexOf(n);
int j=0;
while(j<size)
{
if(adjMatrix[index][j]==1 && vertices.get(j).visited==false)
{
return vertices.get(j);
}
j++;
}
return null;
}
public Iterator<Vertex<T>> bfs()
{
Queue<Vertex<T>> q=new LinkedList<Vertex<T>>();
q.add(this.root);
printVertex(this.root);
root.visited=true;
while(!q.isEmpty())
{
Vertex<T> n=q.remove();
Vertex<T> child=null;
while((child=getUnvisitedChildNode(n))!=null)
{
child.visited=true;
bfsArrList.add(child);
q.add(child);
}
}
clearVertices();
return bfsArrList.iterator();
}
public Iterator<Vertex<T>> dfs()
{
Stack<Vertex<T>> s=new Stack<Vertex<T>>();
s.push(this.root);
root.visited=true;
printVertex(root);
while(!s.isEmpty())
{
Vertex<T> n=s.peek();
Vertex<T> child=getUnvisitedChildNode(n);
if(child!=null)
{
child.visited=true;
dfsArrList.add(child);
s.push(child);
}
else
{
s.pop();
}
}
clearVertices();
return dfsArrList.iterator();
}
private void clearVertices()
{
int i=0;
while(i<size)
{
Vertex<T> n=vertices.get(i);
n.visited=false;
i++;
}
}
private void printVertex(Vertex<T> n)
{
System.out.print(n.label+" ");
}
}
答案 0 :(得分:1)
看here。
如果v可以从u到达,则u是v的前身,v是u的后继者。如果从u到v有弧,则u是v的直接前导,v是u的直接后继。
实现这一点应该是微不足道的,因为你似乎已经建立了邻接矩阵以及遍历函数。所以只需运行BFS / DFS并找到您感兴趣的内容。
请注意,除非您的图表是定向的,否则谈论前辈和后继者是没有意义的,因为边缘是双向的。你的图表似乎是无向的,所以你确定分配是不是要找到一个节点是否可以从另一个节点到达?
答案 1 :(得分:0)
我认为此功能有误:
public void addEdge(Vertex<T> start, Vertex<T> end) {
if (adjMatrix == null) {
size = vertices.size();
adjMatrix = new int[size][size];
}
int startIndex = vertices.indexOf(start);
int endIndex = vertices.indexOf(end);
adjMatrix[startIndex][endIndex] = 1;
adjMatrix[endIndex][startIndex] = 1;
}
第二个任务是有效地说边缘是无方向的。如果我删除第二个任务,那么这个测试
import junit.framework.TestCase;
public class GraphTest extends TestCase {
public void testIsPredecessor() throws Exception {
Graph<Integer> graph = new Graph<Integer>();
Vertex<Integer> zero = new Vertex<Integer>(0, "zero");
Vertex<Integer> one = new Vertex<Integer>(1, "one");
Vertex<Integer> two = new Vertex<Integer>(2, "two");
graph.addVertex(zero);
graph.addVertex(one);
graph.addVertex(two);
graph.addEdge(zero, one);
graph.addEdge(one, two);
assertTrue(graph.isPredecessor(zero, one));
assertFalse(graph.isPredecessor(one, zero));
}
}
可以通过以下实现传递:
public boolean isPredecessor( Vertex<T> a, Vertex<T> b){
int startIndex=vertices.indexOf(a);
int endIndex=vertices.indexOf(b);
return adjMatrix[startIndex][endIndex]==1;
}
isSuccessor()
有一个明显的实现 - 只需致电isPredecessor(b, a)
。顺便说一下,deleteEdge()
方法可能应该分配给0而不是1(并且应该只分配一次,如addEdge()
)。