在java中使用BFS的两个城市之间的路径

时间:2014-12-22 11:22:15

标签: java algorithm graph linked-list singly-linked-list

我正在尝试建立一个数据结构来存储地图内容,如道路和城市信息。我正在使用顶点/城市的链表,当创建顶点/城市时,它会在其构造函数中创建另一个边的链表。 我需要一种算法来找到两个随机城市之间的最短路径。 我修改过的BFS算法不是绝对正常的。 算法:

public void getPath(String from, String to) {
        Queue<cVertex> Q = new LinkedList<cVertex>();
        List<cVertex> visited = new LinkedList<cVertex>();
        cVertex l = null;
        for (int i = 0; i < c.size(); i++) {
            if (c.get(i).cityName.equals(to)) {
                l = c.get(i);
                break;
            }
        }
        for (cVertex a : c) {
            if (a.cityName.equals(from)) {
                // System.out.println(a.cityName);
                Q.add(a);
                System.out.println("\nPath from " + a.cityName + " to "
                        + l.cityName);
                break;
            }
        }
        while (!Q.isEmpty()) {
            cVertex u = Q.remove();
            System.out.print(u.cityName);
            if (u.cityName.equals(l.cityName)) {
                return;
            }
            System.out.print("-->");
            visited.add(u);
            for (cVertex w : c) {
                for (Edge e : w.list) {
                    Edge n = e;
                    for (cVertex d : c) {
                        if (d.cityName.equals(e.to)) {
                            if (!visited.contains(d) && !Q.contains(d))
                                Q.add(d);
                        }
                    }
                }
            }
        }
    }

我需要帮助! e.to表示与此边连接的cityName。

1 个答案:

答案 0 :(得分:1)

你应该在你的问题中说&#34; c&#34;是静态变量,它是一个cVertex数组。 还显示您在getPath函数中使用的所有类的声明和定义,例如: 您的问题中还包括cVertex和Edge类的字段,属性和方法。

我还想让你解释一下我在Java中如何将LinkedList隐式转换为Queue和LinkedList转换为List。我只是想知道。我感兴趣,因为在C#中,所有这些类都存在于System.Collections.Generic命名空间中,但您既不能隐式也不能将LinkedList显式转换为Queue和List。

对于C#:

Queue<cVertex> Q = new LinkedList<cVertex>();
List<cVertex> visited = new LinkedList<cVertex>();

即使在某处声明并定义了类cVertex,这篇文章也是被禁止并且会出错。

但无论如何,你的问题很棒,也很有挑战性。

不幸的是,我从来没有学过Java,所以我不能发布我在语法和语法方面可能不正确的代码,但我仍然理解你的聪明问题,但我仍然可以帮助你,所以我会告诉你我的想法以及为了回答你的问题你必须做些什么。

首先删除或至少从项目中排除您在getPath函数中使用的cVertex和Edge类,并添加一个新类。按名称和#34; City&#34;来呼叫这个班级。此类的实例应将城市名称存储为字符串,并将数组存储为City类型。 在此阵列中,请参考所有可以从this城市前往一条道路或一辆公共汽车甚至步行的城市。

下一步是创建City类的实例,直到您在该区域上创建该国家/地区的所有城市并将它们全部存储在一个数组中。如果您想调用此数组&#34; c&#34;,那么您将被允许。当然,我理解这个数组是静态的非常重要,所以你可以在许多其他函数中使用它。

现在你需要一个接收一个string参数的函数,它是一个城市的名字,它从静态数组返回一个对具有该名称的City实例的引用。

实现此功能非常简单。您只需循环(遍历)所有城市并检查for循环中当前城市的名称是否与字符串参数匹配。如果是,则返回for循环中当前城市的引用,该函数自动停止。如果找不到具有此名称的城市,则该函数当然会返回null。

您可以按名称&#34; findCityByName&#34;。

调用此功能

完成此功能后,下一步是从&#34; getPath&#34;重命名函数getPath。 to&#34; getPaths&#34; (只需添加以结束&#39; s&#39;字母),并将此函数的返回类型从void更改为Boolean。此更改很好,因为此函数的返回值将通知您函数是成功还是失败。如果输入参数无效,则函数将失败并返回false。其他函数成功并返回true

现在添加三个非常必要的参数,以使此功能正常运行。

这个函数的前两个参数是两个你想要的城市名称,就像你在问题中发布的字符串一样,但第三个参数应该是City类型的列表。此列表存储对所访问的所有城市的引用。您可以按名称&#34;访问&#34;来调用此参数。你的错误是定义&#34;访问&#34;作为本地变量,而不是参数

第四个参数也应该是一个列表,但是类型为City的类型数组。此列表中的每个数组都会存储对所有城市的引用,这些城市必须先从您出去的城市到达目标城市。此列表中的每个数组实际上都是一个路径。 此列表包含所有可能的路径,以便从&#34;来自&#34;到达目标城市city,它们的名字在这个函数的前两个参数中指定为字符串。此列表实际上包含您希望从此函数获得的内容。

您可以按名称&#34;路径&#34;。

调用此参数

第五个最后参数也应该是类型City的列表,类似于第三个参数的类型 - &#34;已访问&#34;,但此列表存储对已访问过的城市的引用,但所有不像&#34;访问过&#34;列表参数。这是&#34;访问过的&#34;列出此参数的参数。每次调用getPaths函数结束时,都会删除此列表的最后一个元素,而不是像&#34; visited&#34;列表参数。 &#34;访问&#34; list only 将城市的引用添加到自身。它永远不会删除它们,但最后一个参数中的列表确实如此。

您可以通过不同名称&#34; currentPath&#34;来调用此参数。

请注意,您必须在此功能中多次调用此功能才能实现此功能!

此功能必须递归!

这是这个函数的所有参数,但是非常重要始终将最后三个附加参数(第3,第4和第5个)作为参考传递,而不是作为副本!!! < / p>

如果您将这些参数作为副本传递,赢得功能肯定会有效。

现在终于让我们开始重写这个函数的实现代码。

首先,调用&#34; findCityByName&#34;功能两次,以使城市用于查找它们之间的所有可能路径。如果其中一个或两个都是null,那么return false会立即停止此功能,因为您无法计算其中一个城市之间不存在或两者都存在的两个城市之间的路径!此功能也失败,因为前两个参数之一或两者都无效!

如果两者都不为空,那么两个城市都存在,那么你可以开始循环#34;来自&#34;的数组中的所有城市。你可以去的城市。

如果for循环中的当前城市是您想要去的目标城市,那么分配一个大小为&#34; currentPath&#34;的新数组。列出并复制来自&#34; currentPath&#34;的所有引用。列表到此数组,然后将其添加到&#34;路径&#34; list并返回true以立即停止当前函数,因为找到了路径,并且参数对当前的getPath函数也有效。

否则(如果for循环中的当前城市不是目标城市那么) 添加到两个列表&#34;访问&#34;和&#34; currentPath&#34; for循环中当前城市的引用和召回 getPaths函数,并在第一个参数中输入for循环中当前城市的名称。在第2,第3,第4和第5个参数中,分别输入当前getPaths函数的第2,第3,第4和第5个参数(从标题中选取)。仍然不要忘记传递第3,第4和第5参数作为参考,而不是复制或功能不会工作!

我告诉你在else语句中所做的一切只有在&#34;访问&#34; list还没有包含对for循环中当前城市的引用!否则循环继续到下一个城市。 首先检查一下非常重要。

最后(在for循环之后)if&#34; currentPath&#34;不为空,然后从&#34; currentPath&#34;中删除最后一个 引用来自&#34;访问过&#34;太!!!

然后return true。第一次调用getPaths函数的前两个参数是有效的。功能可能会成功。

这是getPaths函数的所有声明,定义和实现。

请注意,每次调用此函数之前,必须为此函数在最后三个参数中获取的三个列表分配内存。在通过引用此函数传递这些列表之前,通过空构造函数或没有参数的构造函数或者首先将新列表初始化为空的构造函数来分配它们。这在第一次调用getPaths函数时非常重要,所有列出最后三个参数都是空的。

当第一次调用getPaths函数结束并且函数成功时,只有&#34; currentPath&#34;将保持空虚。否则只有&#34;访问&#34;将保持为空。如果函数成功,并且找到了至少一个路径,那么&#34; paths&#34;将填充数据。 只有&#34;路径&#34;很有趣,而不是其他两个,因为它是getPaths函数给出的答案。

在路径列表准备好之后,现在需要通过分配此列表大小的新数组将其转换为Jugged数组City,并从该列表中复制对该数组的所有引用。

Jugged数组是一个数组,它的类型也是数组。

现在让我们定义一个新函数:getShortestPath

此函数只接收City的jugged数组的一个参数,并返回City数组。

实际上它接收路径并返回最短路径。实现此功能的算法非常简单。

首先定义新的局部变量:name&#34; minSize&#34;并键入int并将其指定为jugged数组中第一个数组的大小。

然后定义另一个新的局部变量:name&#34; shortestPath&#34;并键入City&#39;并将其设置为jugged数组中第一个数组的引用。

然后循环其余数组(从第二个数组开始到最后一个数组),如果当前数组的大小小于&#34; minSize&#34;的值,则设置&#34; minSize& #34; to for循环中当前数组的大小和&#34; shortestPath&#34;到for循环中当前数组的引用。

最后,在for循环之后,返回&#34; shortestPath&#34;。

如果您有许多城市,并且getPaths工作时间过长,那么您可以向City类添加展示位置(X和Y坐标为双精度)。

然后删除或评论getShortestPath函数,并从&#34; getPaths&#34;重命名函数getPaths。 to&#34; getShortestPath&#34;,并删除或评论&#34;路径&#34;参数以及与此参数相关的所有代码。同时更改参数名称&#34; currentPath&#34;到&#34;路径&#34;并将此更改应用于函数中的所有实例。

还在if语句中添加另一个 AND 条件,该条件是for循环中的else语句。 在附加条件中,检查for循环中的当前城市是否最接近目标城市。要知道你需要先在for循环之前将另一个for循环添加到&#34; from&#34;中的所有城市。数组,计算并将所有这些城市到目标城市的距离添加到之前分配的新的本地双打列表中。然后声明,定义并实现一个返回双精度列表中最小双精度的函数。然后调用此函数以获取最近城市与目标城市的距离,并将其保存在新的局部变量中:name&#34; min&#34;并输入double

在附加条件下,如果当前城市与目标城市的计算距离大约等于&#34; min&#34;的值,则当前城市是距离目标城市最近的城市。

定义,声明并实现一个接收City的两个参数的新函数,并将它们之间的距离返回为double,并使用此函数来帮助您。

计算两点距离的数学表达式是:

sqrt(pow(x2 - x1,2)+ pow(y2 - y1,2))或sqrt((x2 - x1)^ 2 +(y2 - y1)^ 2)

pow(a,b)= a ^ b,pow(n,2)= n ^ 2

同样在getShortestPath函数中(曾经被名称&#34; getPaths&#34;调用)删除或注释从&#34; path&#34;删除元素的所有行。 (曾经被名字称为#34; currentPath&#34;)

新的分配列表路径为空,在getShortestPath函数调用之前,但在调用之后和通过引用传递之后,&#34; path&#34;填写数据。它应该是&#34;来自&#34;之间的最短路径。城市到&#34;到&#34;城市。

发表评论并告诉我你是否也了解C#,而不仅仅是Java。

我知道C#,所以如果你告诉我是,那么我将在C#中发布代码。

就是这样。我希望这回答了你的问题。尝试这个想法并发表评论告诉我它是否有用。

祝我好运! :d