Ejemplo n.º 1
0
 protected Vertex getUnvisitedChildVertex(Vertex vertex, Vertex parent) {
   Iterator vertices = vertex.getNeighborIterator();
   while (vertices.hasNext()) {
     Vertex child = (Vertex) vertices.next();
     if (!child.isVisited()) {
       return child;
     } else {
       if (!child.equals(parent)) {
         hasCycle = true;
       }
     }
   }
   return null;
 }
  /**
   * Returns the shortest path from a to b in the graph, or null if there is no such path. Assumes
   * all edge weights are nonnegative. Uses Dijkstra's algorithm.
   *
   * @param a the starting vertex
   * @param b the destination vertex
   * @return a Path where the vertices indicate the path from a to b in order and contains a (first)
   *     and b (last) and the cost is the cost of the path. Returns null if b is not reachable from
   *     a.
   * @throws IllegalArgumentException if a or b does not exist.
   */
  public Path shortestPath(Vertex a, Vertex b) {

    List<Vertex> vertexList = new ArrayList<Vertex>();
    VertexComparator vcp = new VertexComparator();
    PriorityQueue<Vertex> vertexQueue =
        new PriorityQueue<Vertex>(10, vcp); // queue for unknow vertex

    // If the start and end vertex are equal
    // return a path containing one vertex and a cost of 0.
    if (a.equals(b)) {
      vertexList.add(a);
      return new Path(vertexList, 0);
    }

    // if the start and end vertex are not equal:

    // if there is no path starting from a, return null
    if (!adj.containsKey(a)) {
      return null;
    }

    // for (Vertex v : this.vertices() ) {
    //    System.out.println(v.known);
    // }

    // initialize before searching path
    for (Vertex v : adj.keySet()) {
      // variables in adj.keySet() are actually pointers pointing to different memory with those in
      // this.vertices()
      // what we need is actually to change those in memory pointed by this.vertices()
      // have no idea why this.vertices.get() method did not work
      // thus I have to implement as below
      Vertex vn = v; // actually this is a bad initialization
      for (Vertex vi : this.vertices()) {
        if (vi.equals(v)) {
          vn = vi;
        }
      }

      vn.known = false;
      // set all vertex distance to infinity
      vn.distance = Integer.MAX_VALUE;
      // vn.distance = 99999;
      vertexQueue.add(vn);
    }
    // System.exit(1);
    // Set source vertex distance to 0
    for (Vertex vn : this.vertices()) {
      if (vn.equals(a)) {
        vertexQueue.remove(vn);
        vn.distance = 0;
        vn.previous = vn;
        // update vn in vertexQueue
        vertexQueue.add(vn);
      }
    }
    // a.distance = 0;
    // a.previous = a;
    // vertexQueue.remove(a);
    // vertexList.add(a);

    Vertex end = b;
    for (Vertex vn : this.vertices()) {
      if (vn.equals(b)) {
        end = vn;
      }
    }
    // for (Vertex v : this.vertices() ) {
    //    System.out.println(v.distance);
    // }
    System.out.println("start searching...");
    // while ( (!vertexQueue.isEmpty()) && (end.known == false) ) { //while there are still unknow
    // vertex and vertex b is unknown
    while ((!vertexQueue
        .isEmpty())) { // while there are still unknow vertex and vertex b is unknown
      // System.out.println("elements in vertexQueue at beginning:");
      // for (Vertex v : vertexQueue ) {
      //    System.out.println(v.getLabel());
      //    System.out.println("distance: " + v.distance);
      // }
      Vertex nt = vertexQueue.poll(); // unknown node with smallest distance
      // System.out.println("marked " + nt + " as known.");
      // System.out.println("its current distance: " + nt.distance);
      nt.known = true;
      for (Edge e : adj.get(nt)) {
        // search for vertex with the same name as e.getDestination() in this.vertices()
        Vertex en = e.getDestination();
        for (Vertex vn : this.vertices()) {
          if (vn.equals(e.getDestination())) {
            en = vn;
          }
        }

        if (!en.known) {
          if ((nt.distance + e.getWeight()) < en.distance) {
            // update en in vertexQueue
            vertexQueue.remove(en);
            en.distance = nt.distance + e.getWeight();
            en.previous = nt;
            vertexQueue.add(en);
          }
        }
      }
    }
    System.out.println("finished computing shortest path.");
    // for (Vertex v : this.vertices() ) {
    //    System.out.println(v.distance);
    // }

    // traverse to get path from a to b
    Vertex tmp = end;
    while (!tmp.equals(a)) {
      vertexList.add(0, tmp); // may need a heap here?
      tmp = tmp.previous;
    }
    vertexList.add(0, a);
    return new Path(vertexList, end.distance);

    // TODO: after searching for all possible path, return null if there is no path from a to b

  }