统一成本搜索

时间:2015-07-18 18:44:50

标签: java search graph tree shortest-path

我无法解决如何解决这个问题。我有一个包含2个城市的.txt文件,它们之间的距离在每一行上都有空格分隔。我的目标是将两个城市作为args,找到最短的路径。我创建了3个班级。主要,节点和道路(边缘)。

public class Node {
    public Node parent;
    public final String cityName;
    public double pathCost;
    public Road[] neighbors;

    public Node(String x){
        cityName = x;
    }

    public String myCity(){
        return cityName;
    }
}

public class Road {
    public final double distance;
    public final Node destination;

    public Road(Node x, double cost){
        distance = cost;
        destination = x;
    }
}

我想知道如何存储节点和边缘。以下代码是我的尝试。它似乎有效,但我觉得效率不高。

public void initNodes(){
    ArrayList<String> cities = new ArrayList<String>();
    for(String line : myLines){
        String[] split = line.split("\\s+");
        if(!cities.contains(split[0]))
        {
            cities.add(split[0]);
            Node n1 = new Node(split[0]);
            myNodes.add(n1);
        }
        if(!cities.contains(split[1]))
        {
            cities.add(split[1]);
            Node n = new Node(split[1]);
            myNodes.add(n);
        }
    }       
}

首次调用该方法为每个城市创建一个Node后,我调用以下方法来创建Roads。

public void initRoads(){
    for(Node n:myNodes){
        for(String line : myLines){
            String[] split = line.split("\\s+");
            if(split[0].equals(n.cityName)){
                for(Node n2:myNodes){
                    if(split[1].equals(n2.cityName)){
                        Road r1 = new Road(n2,Integer.parseInt(split[2]));
                        Road r2 = new Road(n,Integer.parseInt(split[2]));
                        n.neighbors.add(r1);
                        n2.neighbors.add(r2);
                    }
                }
            }
        }
    }
}

对于所有嵌套的for循环,似乎这是不可能的,因为城市和边缘的数量增长。有没有办法解决这个问题而不创建这样的图形?有没有更简单的方法来创建图表?谢谢你的帮助。

1 个答案:

答案 0 :(得分:1)

一目了然,我认为可以在这里改进几点:

  1. 您指的是每条道路都有destination。你没有具体说道路是单向道路,所以把道路变成双向道路是有意义的。

  2. 您正在循环浏览文件两次 - 为什么?当你读完一行后,在添加两个城市(或在Dictionary中找到它们)后,添加道路。

  3. 对城市使用Dictionary,而不是列表。通过这种方式,您可以更快地找到城市,并跳过initRoads()中的第一个(和第二个)循环。

  4. 我还认为道路是一个有ID,两个城市和距离的班级。如果您愿意,每个城市都可以保存与其相关的道路列表。

  5. 我不是Java的本地人,但总的想法应该是这样的:

        public class Node {
            public Node parent;
            public final String cityName;
            public double pathCost;
            public int[] roads;
    
            public Node(String x){
                cityName = x;
            }
    
            public String myCity(){
                return cityName;
            }
        }
    
        public class Road {
            public final int ID;
            public final double distance;
    
            public Road(int id, double cost){
                ID = id;
                distance = cost;
            }
        }
    
        public Dictionary<String> cities = new Dictionary<String>();
    
        public void initNodes(){
            int curID = 0;
            Node first, second;
            for(String line : myLines){
                String[] split = line.split("\\s+");
                first = getNode(split[0]);
                second = getNode(split[1]);
    
                Road r1 = new Road(curID,split[2]);
                first.roads.add(curID);
                second.roads.add(curID);
                curID++;        
            }       
        }
    
        // Like a singleton...
        public void getNode(string cityName){
    
            if(!cities.contains(cityName))
            {
                Node newCity = new Node(cityName);
                cities.add(cityName, newCity);
            }
            return cities.get(cityName);    
        }