Java递归搜索中的路径堆栈

时间:2009-12-31 12:59:56

标签: java search recursion

我写了一个简单的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提前!!

1 个答案:

答案 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;
   }

}