两个类,相同的代码,一个获取StackOverflow

时间:2015-11-22 01:09:28

标签: java recursion graph stack-overflow

我正在一个通过图表递归执行DFS的项目。

问题是我在两个不同的类(具有不同的名称)中具有完全相同的代码,并且一个设法有效地执行递归,另一个失败并抛出StackOverflowError。这是相同的计算和相同的过程,他们试图解决相同的代码。这有什么理由吗?

修改

以下是代码:

package mundo.ParteA;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.BitSet;
import java.util.Set;

import estructuras.GrafoDirigidoLAdy;
import estructuras.HashTable;
import estructuras.ListaDoble;
import estructuras.Dijkstra.DijkstrasSP;
import mundo.PesosProyecto3;
import mundo.ProcessCSV;
import mundo.Punto;
import mundo.VerticeBogota;

public class ParteAA {

    //-----------------------------------------------------------------
    // Constantes
    //-----------------------------------------------------------------

    /**
     * Constante que establece la ubicación del archivo kml que se produce al calcular la
     * ruta entre dos puntos del grafo
     */
    private static final String OUTPUT_FILE = "./data/outputParteA";

    //-----------------------------------------------------------------
    // Atributos
    //-----------------------------------------------------------------

    private HashTable<String, String> definitions;

    private GrafoDirigidoLAdy<Integer, VerticeBogota> grafoVerticesBogota;

    private HashTable<String, Set<Integer>> diccionarioNombres;

    private HashTable<Punto, VerticeBogota> diccionarioCoordenadas;

    private int numArchivo;

    //-----------------------------------------------------------------
    // Constructor
    //-----------------------------------------------------------------

    public ParteAA()
    {
        numArchivo = 0;
        cargarDatos();
    }

    //-----------------------------------------------------------------
    // Métodos
    //-----------------------------------------------------------------

    public static void main(String... args)
    {
        ParteAA x = new ParteAA();
        for(Integer i : x.centrosAcopioEnRango(4277, 70)){
            System.out.println(i);
        }

//      try {
//          for(Integer i: x.calcularRutaMasCortaDistanciaYMostrarlaEnMaps(3077, 123512, 3, 7))
//              System.out.println(i);
//      } catch (Exception e) {
//          // TODO Auto-generated catch block
//          e.printStackTrace();
//      }
    }

    /**
     * Método que carga los datos para la inicialización.
     */
    public void cargarDatos()
    {
        ProcessCSV csv = new ProcessCSV(PesosProyecto3.TipoPesos.DISTANCIA);
        definitions = csv.getDefinitions();
        grafoVerticesBogota = csv.getGrafo();
        diccionarioNombres = csv.getDiccionarioNombres();
        diccionarioCoordenadas = csv.getDiccionarioCoordenadas();
    }

    /**
     * Método que se encarga de calcular la ruta más corta entre dos nodos y representarla en GoogleMaps
     * @param origen
     * @param destino
     * @param espacioBusquedaOrigen
     * @param espacioBusquedaDestino
     * @return 
     */
    public Iterable<Integer> calcularRutaMasCortaDistanciaYMostrarlaEnMaps(int idOrigen, int idDestino, double espacioBusquedaOrigen , double espacioBusquedaDestino) throws Exception
    {
        VerticeBogota origen = grafoVerticesBogota.getVertice(idOrigen);
        VerticeBogota destino = grafoVerticesBogota.getVertice(idDestino);
        if(origen==null||destino==null){ 
            System.out.println("No existe alguno de los dos vertices ingresados por parámetro. \nHasta Luego!");
            System.exit(0);
        }
        ListaDoble<Integer> listaSalida = (ListaDoble<Integer>) centrosAcopioEnRango(idOrigen, espacioBusquedaOrigen);
        ListaDoble<Integer> listaLlegada = (ListaDoble<Integer>) centrosAcopioEnRango(idDestino, espacioBusquedaDestino);

        if(listaSalida.isEmpty() || listaLlegada.isEmpty())
        {
            throw new Exception("No hay ningún centro de acopio en alguno de los rangos dados. \nPor favor incremente el área de busqueda");
        }

        double distMenor = Double.POSITIVE_INFINITY;
        Iterable<Integer> rutaOptima = null;

        for(Integer i : listaSalida)
        {
            DijkstrasSP sp = new DijkstrasSP(grafoVerticesBogota, i);
            for(Integer j : listaLlegada)
            {
                if(sp.distTo(j)<distMenor)
                {
                    distMenor = sp.distTo(j);
                    if(distMenor==0)
                    {
                        distMenor = 0;
                    }
                    rutaOptima = sp.caminoA(j);
                }
            }
        }

        System.out.println(distMenor);
        getShortestPathFile(rutaOptima);
        return rutaOptima;
    }

    /**
     * Calcula la distancia entre dos puntos.
     * @param origen - Punto inicial.
     * @param destino - Punto de llegada.
     * @return distKm - La distancia en kilometros entre los dos puntos.
     */
    private static double haversineDist(Punto origen, Punto destino)
    {
        long radioTierra = 6371;
        double rad = Math.PI/180;
        return Math.acos(
                Math.sin(origen.getLatitude()*rad) * Math.sin(destino.getLatitude()*rad)
                +   Math.cos(origen.getLatitude()*rad) * Math.cos(destino.getLatitude()*rad)
                *   Math.cos(destino.getLongitude()*rad - origen.getLongitude()*rad)
                ) * radioTierra;
    }

    /**
     * Método que busca los centros de acopio que están dentro del radio de búsqueda dada una ubicación
     */
    private Iterable<Integer> centrosAcopioEnRango(int origen, double distKm)
    {
        BitSet marked = new BitSet(grafoVerticesBogota.getNumVertices());
        ListaDoble<Integer> verticesEnRango = new ListaDoble<Integer>();

        haversineDFS(verticesEnRango, marked, origen, origen, distKm);

        return verticesEnRango;
    }

    private void haversineDFS(ListaDoble<Integer> verticesEnRango, BitSet marked, int orig, int actual, double distKm) {
        marked.set(actual);
        if(grafoVerticesBogota.getVertice(actual).isCentroDeAcopio()){ verticesEnRango.add(actual); }
        for(GrafoDirigidoLAdy<Integer, VerticeBogota>.Arco arc : grafoVerticesBogota.getAdy(actual))
        {
            double dis = haversineDist(grafoVerticesBogota.getVertice(orig).getUbicacion(), arc.getTo().getUbicacion());
            if(dis<=distKm && !marked.get(arc.getTo().getId()))
            {
                haversineDFS(verticesEnRango, marked, orig, arc.getTo().getId(), distKm);
            }
        }
    }

    //-----------------------------------------------------------------
    // KML Output
    //-----------------------------------------------------------------

    /**
     * Escribe el archivo kml de salida con la información de la ruta más corta del nodo idSource al nodo idDestination
     * Este archivo se puede importar a google maps para visualizar la ruta
     * @param idSource int El identificador de la fuente
     * @param idDestination int El identificador del destino
     */
    private void getShortestPathFile(Iterable<Integer> ruta)  {
        numArchivo++;
        File f = new File(OUTPUT_FILE+numArchivo+".kml");
        try {

            if(!f.exists()) {
                f.createNewFile();
            }

            FileWriter fw = new FileWriter(f);
            PrintWriter pw = new PrintWriter(fw);

            writeKMLHeader(pw);

            for(Integer i : ruta)
            {
                pw.println("        " + grafoVerticesBogota.getVertice(i).getUbicacion().getLongitude() + ", " + grafoVerticesBogota.getVertice(i).getUbicacion().getLatitude());
            }

            writeKMLFooter(pw);
            fw.flush();
            fw.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Escribe el encabezado de un archivo kml
     * @param pw El PrintWriter que escribe al archivo
     * @throws IOException En caso de que haya un error a la hora de escribir en el archivo
     */
    private void writeKMLHeader(PrintWriter pw) throws IOException
    {

        pw.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        pw.println("<kml xmlns=\"http://www.opengis.net/kml/2.2\">");
        pw.println("  <Document>");
        pw.println("    <name>Ruta más corta</name>");
        pw.println("    <Placemark>");
        pw.println("      <name>Ruta más corta</name>");
        pw.println("      <LineString>");
        pw.println("      <altitudeMode>absolute</altitudeMode>");
        pw.println("      <coordinates>");
    }

    /**
     * Escribe el pie de pagina de un archivo kml
     * @param pw El PrintWriter que escribe al archivo
     * @throws IOException En caso de que haya un error a la hora de escribir en el archivo
     */
    private void writeKMLFooter(PrintWriter pw) throws IOException
    {
        pw.println("      </coordinates>");
        pw.println("      </LineString>");
        pw.println("    </Placemark>");
        pw.println("  </Document>");
        pw.println("</kml>");
    }

    //-----------------------------------------------------------------
    // Getters y Setters
    //-----------------------------------------------------------------

    public HashTable<String, String> getDefinitions() {
        return definitions;
    }

    public void setDefinitions(HashTable<String, String> definitions) {
        this.definitions = definitions;
    }

    public GrafoDirigidoLAdy<Integer, VerticeBogota> getGrafoVerticesBogota() {
        return grafoVerticesBogota;
    }

    public void setGrafoVerticesBogota(GrafoDirigidoLAdy<Integer, VerticeBogota> grafoVerticesBogota) {
        this.grafoVerticesBogota = grafoVerticesBogota;
    }

    public HashTable<String, Set<Integer>> getDiccionarioNombres() {
        return diccionarioNombres;
    }

    public void setDiccionarioNombres(HashTable<String, Set<Integer>> diccionarioNombres) {
        this.diccionarioNombres = diccionarioNombres;
    }

    public HashTable<Punto, VerticeBogota> getDiccionarioCoordenadas() {
        return diccionarioCoordenadas;
    }

    public void setDiccionarioCoordenadas(HashTable<Punto, VerticeBogota> diccionarioCoordenadas) {
        this.diccionarioCoordenadas = diccionarioCoordenadas;
    }
}

这是另一个:

package mundo.ParteB;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.BitSet;
import java.util.Set;

import estructuras.GrafoDirigidoLAdy;
import estructuras.HashTable;
import estructuras.ListaDoble;
import estructuras.Dijkstra.DijkstrasSP;
import mundo.PesosProyecto3;
import mundo.ProcessCSV;
import mundo.Punto;
import mundo.VerticeBogota;

public class ParteBB{

    //-----------------------------------------------------------------
    // Constantes
    //-----------------------------------------------------------------

    /**
     * Constante que establece la ubicación del archivo kml que se produce al calcular la
     * ruta entre dos puntos del grafo
     */
    private static final String OUTPUT_FILE = "./data/outputParteA";

    //-----------------------------------------------------------------
    // Atributos
    //-----------------------------------------------------------------

    private HashTable<String, String> definitions;

    private GrafoDirigidoLAdy<Integer, VerticeBogota> grafoVerticesBogota;

    private HashTable<String, Set<Integer>> diccionarioNombres;

    private HashTable<Punto, VerticeBogota> diccionarioCoordenadas;

    private int numArchivo;

    //-----------------------------------------------------------------
    // Constructor
    //-----------------------------------------------------------------

    public ParteBB()
    {
        numArchivo = 0;
        cargarDatos();
    }

    //-----------------------------------------------------------------
    // Métodos
    //-----------------------------------------------------------------

    public static void main(String... args)
    {
        ParteBB x = new ParteBB();
        for(Integer i : x.centrosAcopioEnRango(4277, 70)){
            System.out.println(i);
        }

//      try {
//          for(Integer i: x.calcularRutaMasCortaDistanciaYMostrarlaEnMaps(3077, 123512, 3, 7))
//              System.out.println(i);
//      } catch (Exception e) {
//          // TODO Auto-generated catch block
//          e.printStackTrace();
//      }
    }

    /**
     * Método que carga los datos para la inicialización.
     */
    public void cargarDatos()
    {
        ProcessCSV csv = new ProcessCSV(PesosProyecto3.TipoPesos.DISTANCIA);
        definitions = csv.getDefinitions();
        grafoVerticesBogota = csv.getGrafo();
        diccionarioNombres = csv.getDiccionarioNombres();
        diccionarioCoordenadas = csv.getDiccionarioCoordenadas();
    }

    /**
     * Método que se encarga de calcular la ruta más corta entre dos nodos y representarla en GoogleMaps
     * @param origen
     * @param destino
     * @param espacioBusquedaOrigen
     * @param espacioBusquedaDestino
     * @return 
     */
    public Iterable<Integer> calcularRutaMasCortaDistanciaYMostrarlaEnMaps(int idOrigen, int idDestino, double espacioBusquedaOrigen , double espacioBusquedaDestino) throws Exception
    {
        VerticeBogota origen = grafoVerticesBogota.getVertice(idOrigen);
        VerticeBogota destino = grafoVerticesBogota.getVertice(idDestino);
        if(origen==null||destino==null){ 
            System.out.println("No existe alguno de los dos vertices ingresados por parámetro. \nHasta Luego!");
            System.exit(0);
        }
        ListaDoble<Integer> listaSalida = (ListaDoble<Integer>) centrosAcopioEnRango(idOrigen, espacioBusquedaOrigen);
        ListaDoble<Integer> listaLlegada = (ListaDoble<Integer>) centrosAcopioEnRango(idDestino, espacioBusquedaDestino);

        if(listaSalida.isEmpty() || listaLlegada.isEmpty())
        {
            throw new Exception("No hay ningún centro de acopio en alguno de los rangos dados. \nPor favor incremente el área de busqueda");
        }

        double distMenor = Double.POSITIVE_INFINITY;
        Iterable<Integer> rutaOptima = null;

        for(Integer i : listaSalida)
        {
            DijkstrasSP sp = new DijkstrasSP(grafoVerticesBogota, i);
            for(Integer j : listaLlegada)
            {
                if(sp.distTo(j)<distMenor)
                {
                    distMenor = sp.distTo(j);
                    if(distMenor==0)
                    {
                        distMenor = 0;
                    }
                    rutaOptima = sp.caminoA(j);
                }
            }
        }

        System.out.println(distMenor);
        getShortestPathFile(rutaOptima);
        return rutaOptima;
    }

    /**
     * Calcula la distancia entre dos puntos.
     * @param origen - Punto inicial.
     * @param destino - Punto de llegada.
     * @return distKm - La distancia en kilometros entre los dos puntos.
     */
    private static double haversineDist(Punto origen, Punto destino)
    {
        long radioTierra = 6371;
        double rad = Math.PI/180;
        return Math.acos(
                Math.sin(origen.getLatitude()*rad) * Math.sin(destino.getLatitude()*rad)
                +   Math.cos(origen.getLatitude()*rad) * Math.cos(destino.getLatitude()*rad)
                *   Math.cos(destino.getLongitude()*rad - origen.getLongitude()*rad)
                ) * radioTierra;
    }

    /**
     * Método que busca los centros de acopio que están dentro del radio de búsqueda dada una ubicación
     */
    private Iterable<Integer> centrosAcopioEnRango(int origen, double distKm)
    {
        BitSet marked = new BitSet(grafoVerticesBogota.getNumVertices());
        ListaDoble<Integer> verticesEnRango = new ListaDoble<Integer>();

        haversineDFS(verticesEnRango, marked, origen, origen, distKm);

        return verticesEnRango;
    }

    private void haversineDFS(ListaDoble<Integer> verticesEnRango, BitSet marked, int orig, int actual, double distKm) {
        marked.set(actual);
        if(grafoVerticesBogota.getVertice(actual).isCentroDeAcopio()){ verticesEnRango.add(actual); }
        for(GrafoDirigidoLAdy<Integer, VerticeBogota>.Arco arc : grafoVerticesBogota.getAdy(actual))
        {
            double dis = haversineDist(grafoVerticesBogota.getVertice(orig).getUbicacion(), arc.getTo().getUbicacion());
            if(dis<=distKm && !marked.get(arc.getTo().getId()))
            {
                haversineDFS(verticesEnRango, marked, orig, arc.getTo().getId(), distKm);
            }
        }
    }

    //-----------------------------------------------------------------
    // KML Output
    //-----------------------------------------------------------------

    /**
     * Escribe el archivo kml de salida con la información de la ruta más corta del nodo idSource al nodo idDestination
     * Este archivo se puede importar a google maps para visualizar la ruta
     * @param idSource int El identificador de la fuente
     * @param idDestination int El identificador del destino
     */
    private void getShortestPathFile(Iterable<Integer> ruta)  {
        numArchivo++;
        File f = new File(OUTPUT_FILE+numArchivo+".kml");
        try {

            if(!f.exists()) {
                f.createNewFile();
            }

            FileWriter fw = new FileWriter(f);
            PrintWriter pw = new PrintWriter(fw);

            writeKMLHeader(pw);

            for(Integer i : ruta)
            {
                pw.println("        " + grafoVerticesBogota.getVertice(i).getUbicacion().getLongitude() + ", " + grafoVerticesBogota.getVertice(i).getUbicacion().getLatitude());
            }

            writeKMLFooter(pw);
            fw.flush();
            fw.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Escribe el encabezado de un archivo kml
     * @param pw El PrintWriter que escribe al archivo
     * @throws IOException En caso de que haya un error a la hora de escribir en el archivo
     */
    private void writeKMLHeader(PrintWriter pw) throws IOException
    {

        pw.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        pw.println("<kml xmlns=\"http://www.opengis.net/kml/2.2\">");
        pw.println("  <Document>");
        pw.println("    <name>Ruta más corta</name>");
        pw.println("    <Placemark>");
        pw.println("      <name>Ruta más corta</name>");
        pw.println("      <LineString>");
        pw.println("      <altitudeMode>absolute</altitudeMode>");
        pw.println("      <coordinates>");
    }

    /**
     * Escribe el pie de pagina de un archivo kml
     * @param pw El PrintWriter que escribe al archivo
     * @throws IOException En caso de que haya un error a la hora de escribir en el archivo
     */
    private void writeKMLFooter(PrintWriter pw) throws IOException
    {
        pw.println("      </coordinates>");
        pw.println("      </LineString>");
        pw.println("    </Placemark>");
        pw.println("  </Document>");
        pw.println("</kml>");
    }

    //-----------------------------------------------------------------
    // Getters y Setters
    //-----------------------------------------------------------------

    public HashTable<String, String> getDefinitions() {
        return definitions;
    }

    public void setDefinitions(HashTable<String, String> definitions) {
        this.definitions = definitions;
    }

    public GrafoDirigidoLAdy<Integer, VerticeBogota> getGrafoVerticesBogota() {
        return grafoVerticesBogota;
    }

    public void setGrafoVerticesBogota(GrafoDirigidoLAdy<Integer, VerticeBogota> grafoVerticesBogota) {
        this.grafoVerticesBogota = grafoVerticesBogota;
    }

    public HashTable<String, Set<Integer>> getDiccionarioNombres() {
        return diccionarioNombres;
    }

    public void setDiccionarioNombres(HashTable<String, Set<Integer>> diccionarioNombres) {
        this.diccionarioNombres = diccionarioNombres;
    }

    public HashTable<Punto, VerticeBogota> getDiccionarioCoordenadas() {
        return diccionarioCoordenadas;
    }

    public void setDiccionarioCoordenadas(HashTable<Punto, VerticeBogota> diccionarioCoordenadas) {
        this.diccionarioCoordenadas = diccionarioCoordenadas;
    }
}

2 个答案:

答案 0 :(得分:1)

一种情况是您成功构建代码,然后更改代码并认为它​​已正确编译,但它没有,所以我猜测您认为相同的代码可能不是&# 39; t实际上是相同的代码。

另外,我假设你两次使用相同的输入。

答案 1 :(得分:1)

好的,我已经弄清楚它是什么,运行配置。对于一个班级设置了更大的堆栈,我花了一段时间才注意到!非常感谢所有帮助过的人!