我写了一个简单的Depth-First搜索算法,但是无法正确构建补丁。我很难理解,为什么 - 所以,基本上,需要你的帮助,伙计们:)
以下是代码:
public void Search(String from, String to) {
String depart = from;
String destin = to;
if ( (NoChildren(depart) == false)
&& (!depart.equalsIgnoreCase(destin)) ) {
while (!depart.equalsIgnoreCase(to)) {
closeStack.push(depart);
depart = getChildren(depart);
}
}
}
public boolean NoChildren(String from) {
boolean noChildren = false;
int counter = 0;
for(int j = 0; j < Flights.size(); j++) {
FlightInfo flight = (FlightInfo)Flights.elementAt(j);
if (flight.from().equalsIgnoreCase(from)) {
counter++;
}
}
if (counter == 0) {
noChildren = true;
}
return noChildren;
}
public String getChildren(String from) {
for(int j = 0; j < Flights.size(); j++) {
FlightInfo flight = (FlightInfo)Flights.elementAt(j);
if (flight.from().equalsIgnoreCase(from)) {
openStack.push(flight.to().toString());
}
}
return openStack.pop().toString();
}
我只是为了清理时间更长,并计划优化它 - 只需要让它首先正常工作:))
好吧,主要问题在于closeStack,它意味着包含从开始到结束的路径 - 但现在,它包含所检查的算法: - [
Thanx提前!!
答案 0 :(得分:4)
Maxim,您的代码中存在大量错误。看起来好像你对你想要做的事情有所了解,然后向它扔了一些代码,直到某些东西出现并运作了一下,但这里没有明确的概念,因此难怪它不是真的很有效。
这个程序的核心是Flights集合(为什么Flights
是大写的?),并且很有可能围绕它构建一个工作路径查找器。我不确定是否会帮助你更多地给你一些提示或者只是为你构建程序。
更新:我同时为波兰航空公司找到了一个航班时刻表(请不要问!),我有203条不同的航线可以用来填补和测试航班连接结构。我将开始黑客攻击,我们会看到它是怎么回事。
更新:以下是代码。
尽管对你的明显目的有用,但仅仅找到路线(即所访问的机场的行程)可能还不够;你可能想要一个到达那里的航班列表。当然,请注意,可能有多个具有相同行程的航班组合 - 此代码只找到第一个。
您可能想要修改算法以在旅行时间上设置一个重量(=成本),如果您有这些权重,那么您的乘客不仅可以获得最少数量的腿(=从一个机场到下一个机场的跳跃),还可以最短的组合旅行时间。这种更通用的算法形式称为Dijkstra算法,也在维基百科中有描述。
有趣的是,似乎BFS并不适合递归解决方案。就像你的原始代码一样,我的代码基本上是必须的,有几个循环。请注意,执行BFS的正确“主”数据结构不是堆栈而是队列!
public class Maxim {
/**
* Create a Maxim instance and run a search on it.
*/
public static void main(String[] args) {
try {
Maxim maxim = new Maxim();
Route r = maxim.findRoute("FCO", "DNV"); // tests a single origin/destination pair
if (r == null) {
System.out.println("No route found");
} else {
System.out.println(Arrays.deepToString(r.toArray()));
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* A simple Flight. Contains a flight number and only a single leg.
* number: Flight number
* dep: Departure airport
* arr: Arrival airport
*/
class Flight {
final String number, dep, arr;
public Flight(String number, String departure, String arrival) {
this.number = number; this.dep = departure; this.arr = arrival;
}
public String toString() {
return "Flight [number=" + this.number + ", dep=" + this.dep + ", arr=" + this.arr + "]";
}
}
/**
* Airport: A city and a list of Flights originating from it.
*/
class Airport {
public final String city;
public List<Flight> flights = new ArrayList<Flight>();
public Airport(String city) {
this.city = city;
}
public String toString() {
return "Airport [city=" + this.city + ", flights=" + this.flights + "]";
}
}
/**
* Route: A list of flights that get a traveller from a given origin to a destination.
*/
static class Route extends ArrayList<Flight> { }
/**
* Our known list of flights. It's not really needed after initialization.
*/
private List<Flight> flights = new ArrayList<Flight>();
/**
* List of airports. These constitute the graph we search.
*/
private Map<String, Airport> airports = new HashMap<String, Airport>();
/**
* Constructor. Constructs the "airports" graph from a list of "flights" read from a file.
*/
public Maxim() throws Exception {
// Read flights from file into list "flights".
// The file contains strings like " 696KGDWAW" = flight number, departure airport, arrival airport
BufferedReader flightReader = new BufferedReader(new FileReader("/home/carl/XX.flights"));
while (true) {
String flt = flightReader.readLine();
if (flt == null) break;
flights.add(new Flight(flt.substring(0,4), flt.substring(4, 7), flt.substring(7, 10)));
}
flightReader.close();
// Create a map of each airport to a list of Flights departing from it.
// This is the graph we'll be doing BFS on.
for (Flight flight : flights) {
String from = flight.dep;
if (!airports.containsKey(from)) {
Airport port = new Airport(from);
port.flights.add(flight);
airports.put(from, port);
} else {
Airport port = airports.get(from);
port.flights.add(flight);
}
}
}
/**
Algorithm (from Wikipedia):
1. Enqueue the root node.
2. Dequeue a node and examine it.
If the element sought is found in this node, quit the search and return a result.
Otherwise enqueue any successors (the direct child nodes) that have not yet been discovered.
3. If the queue is empty, every node on the graph has been examined – quit the search and return "not found".
4. Repeat from Step 2.
*/
public Route findRoute(String origin, String destination) {
Queue<Airport> queue = new LinkedList<Airport>();
Map<Airport, Flight> backtrack = new HashMap<Airport, Flight>();
Airport oriApt = this.airports.get(origin);
if (oriApt == null) return null; // origin airport not found - no solution
queue.add(oriApt);
while (!queue.isEmpty()) {
Airport apt = queue.remove();
if (apt == null) break;
if (apt.city.equals(destination)) { // Made it to destination; create the route and return it
Route toHere = new Route();
while (apt != oriApt) {
Flight flt = backtrack.get(apt);
toHere.add(flt);
apt = airports.get(flt.dep);
}
Collections.reverse(toHere);
return toHere;
}
// enqueue all new airports reachable from this airport.
// record the flight that got us there in backtrack.
for (Flight flt: apt.flights) {
Airport destApt = airports.get(flt.arr);
if (backtrack.containsKey(destApt)) continue; // we've been to this destination before - ignore
backtrack.put(destApt, flt);
queue.add(destApt);
}
}
// if we're here, we didn't find anything.
return null;
}
}