2009-12-31 24 views
1

我寫了一個簡單的深度優先搜索算法,它可以工作,但無法構建正確的補丁。有一個艱難的時間試圖理解,爲什麼林 - 所以,基本上,需要你的幫助,球員:)Java遞歸搜索中的路徑堆棧

下面是代碼:

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提前!!

+2

這是一個遞歸搜索?你沒有遞歸功能。 – 2009-12-31 13:11:05

+1

遞歸*可以使用堆棧進行模擬,因爲OP正在嘗試這樣做。但是,這一切都很混亂。 – 2009-12-31 13:14:16

+1

@Carl:是的,這裏沒有回溯或任何事情發生。它將穿過「飛行」對象,直到找到沒有目的地的對象,然後停止。拯救這個代碼是完全重寫它的問題。 – Welbog 2009-12-31 13:16:18

回答

4

Maxim,你的代碼中有一大堆錯誤。看起來好像你有想法想要做什麼,然後向它投擲一些代碼,直到出現並工作了一點,但這裏沒有明確的概念,因此難怪它不起作用。

這個程序的核心是航班收集(爲什麼Flights大寫?),並且很有可能在它周圍建立一個工作路線查找器。我不確定它是否會幫助您更多地給您一些提示或爲您構建程序。


更新:我同時發現了一個航班時刻表波蘭航空公司(不要問!)與203條不同的路線,我可以用它來填充和測試飛行連接結構。我將開始黑客攻擊,然後我們會看到它是如何發生的。


更新:下面的代碼。爲了達到您的目的,您可能僅僅找到路線(即參觀機場的行程)可能還不夠。你可能想要一個到達那裏的航班清單。請注意,當然,可能有多個具有相同行程的航班組合 - 此代碼只能找到第一個航班。

您可能希望修改算法以在旅行時間上設置重量(=成本),如果您有這些重量,那麼您的乘客不會得到最少的腿數(=從一個機場到下一個機場的跳數),但也是最短的組合旅行時間。該算法的更一般形式將被稱爲Dijkstra算法,並且在Wikipedia中也有描述。

有趣的是,似乎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; 
    } 

} 
+1

Awww,你怎麼得到所有的樂趣? – 2009-12-31 13:58:39

+0

你怎麼能讓它返回多條路線?我已經測試過它,但只返回一條路線 – franklinexpress 2015-07-06 13:33:35

+0

@Franklin,我使用的算法是尋找第一條最短路徑。如果你真的想列舉不同的可能路徑,這一個不會這樣做,我沒有一個方便的。如果我這樣做了,那麼與目前的問題無關,所以我建議你問這是一個新問題。 – 2015-07-23 15:19:16