我正在编写一个模仿Java命令行编译器的Java程序。它需要读入一个文本文件,并将其转换为有向图。然后,用户应该输入他们希望重新编译的类,并且它应该显示要重新编译类的顺序。
说有一个包含以下内容的文本文件
ClassA ClassC ClassE
ClassB ClassD ClassG
ClassE ClassB ClassF ClassH
ClassI ClassC
然后用户决定要重新编译ClassA。重新编译类的顺序如下:
ClassA ClassE ClassH ClassF ClassB ClassG ClassD ClassC
但是每当我尝试进行拓扑排序时,我都会得到一个循环异常(这是一个异常,只要检测到循环就会抛出)。当我尝试使用可以工作的类时,我只能在输出文本字段中输入我输入的类。我该怎么做才能解决这个问题?
定向图类
import java.io.*;
import java.util.*;
public class directedGraph2<T>
{
private ArrayList<LinkedList> vertices;
private Map<T, Integer>data;
private LinkedList<Integer> adjacencyList;
boolean[] found;
boolean[] completed;
public directedGraph2()
{
vertices=new ArrayList<LinkedList>();
data=new HashMap<T,Integer>();
}
public void addEdges(T from, T to)
{
if(!data.containsKey(from))
{
data.put(from, data.size());
int index=(int)data.get(from);
vertices.add(index, new LinkedList<Integer>());
}
if(!data.containsKey(to))
{
data.put(to, data.size());
int index=(int)data.get(to);
vertices.add(index, new LinkedList<Integer>());
}
int fromIndex=(int) data.get(from);
int toIndex=(int) data.get(to);
vertices.get(fromIndex).add(toIndex);
}
public void depthFirstSearch(int index) throws CycleException
{
if(found[index])
{
throw new CycleException("No");
}
if(completed[index])
{
return;
}
found[index]=true;
LinkedList<Integer> aList=(LinkedList<Integer>)vertices.get(index).clone();
while(!aList.isEmpty())
{
int nextIndex=aList.pop();
depthFirstSearch(nextIndex);
}
completed[index]=true;
adjacencyList.push(index);
}
public String topSort(T indexName) throws InvalidClassNameException, CycleException
{
if(!data.containsKey(indexName))
{
throw new InvalidClassNameException("Nope sorry");
}
String topOrder="";
int index=(int)data.get(indexName);
found=new boolean[vertices.size()];
completed=new boolean[vertices.size()];
adjacencyList=new LinkedList<Integer>();
depthFirstSearch(index);
while(!adjacencyList.isEmpty())
{
int index2=adjacencyList.pop();
topOrder+=indexToName(index2)+" ";
}
return topOrder;
}
public T indexToName(int index)
{
for(Map.Entry<T, Integer>toConvert:data.entrySet())
{
if(toConvert.getValue().equals(index))
{
return toConvert.getKey();
}
}
return null;
}
public void readFrom(String file) throws IOException, FileNotFoundException
{
vertices=new ArrayList<LinkedList>();
data=new HashMap<T,Integer>();
FileReader myReader=null;
BufferedReader myBufferedReader=null;
try
{
myReader=new FileReader(file);
}
catch(FileNotFoundException f)
{
throw new FileNotFoundException("File couldn't be found");
}
try
{
myBufferedReader=new BufferedReader(myReader);
String lineToRead;
T[] tokens;
T vertex;
int index;
while((lineToRead=myBufferedReader.readLine())!=null)
{
lineToRead=lineToRead.trim();
if(!lineToRead.isEmpty())
{
tokens=(T[]) lineToRead.split(" ");
vertex=tokens[0];
if(!data.containsKey(vertex))
{
data.put((T) vertex, data.size());
index=(int)data.get(vertex);
vertices.add(index, new LinkedList<Integer>());
}
if(tokens.length>1)
{
for(int i=0;i<tokens.length;i++)
{
addEdges(vertex,tokens[i]);
}
}
}
}
myBufferedReader.close();
}
catch(IOException e)
{
throw new IOException("File can't open");
}
}
GUI
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.*;
import java.util.*;
public class graphGUI扩展了JPanel {
directedGraph2 test=new directedGraph2();
private JFrame frame;//The frame
private JPanel panel;//The panel
private JLabel inputFile;
private JTextField input;
private JButton buildGraph;
private JLabel classToRecompile;
private JTextField classInput;
private JButton recompileClass;
private JTextField output;
//Builds the GUI
public graphGUI()
{
frame=new JFrame("Graph GUI");
panel=new JPanel();
inputFile=new JLabel("Input file name");
input=new JTextField("");
buildGraph=new JButton("Build Directed Graph");
classToRecompile=new JLabel("Class to recompile");
classInput=new JTextField("");
recompileClass=new JButton("Topological Order");
output=new JTextField("");
//Adding the parts together
panel.setLayout(new GridLayout(3,3));
panel.add(inputFile);
panel.add(input);
panel.add(buildGraph);
panel.add(classToRecompile);
panel.add(classInput);
panel.add(recompileClass);
panel.add(output);
frame.add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setSize(600,300);
frame.setBackground(Color.red);
frame.setVisible(true);;
buildGraph.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String file=input.getText();
try {
test.readFrom(file);
JOptionPane.showMessageDialog(null, "File successfully opened");
} catch (IOException e1) {
JOptionPane.showMessageDialog(null, "File failed to open");
}
}
});
recompileClass.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String recompileClass=classInput.getText();
try
{
output.setText(test.topSort(recompileClass));
}
catch(CycleException c)
{
c.printStackTrace();
JOptionPane.showMessageDialog(null, "Cycle detected");
}
};
});
}
//Main method
public static void main(String[] args)
{
graphGUI myGUI=new graphGUI();
}
}
循环异常类
public class CycleException extends RuntimeException
{
private String s;
public CycleException(String s)
{
this.s=s;
}
public String getString()
{
return s;
}
}
异常堆栈
CycleException
at directedGraph2.depthFirstSearch(directedGraph2.java:47)
at directedGraph2.depthFirstSearch(directedGraph2.java:59)
at directedGraph2.topSort(directedGraph2.java:77)
at graphGUI$2.actionPerformed(graphGUI.java:120)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)