簡體   English   中英

在Java中使用BFS的兩個城市之間的路徑

[英]Path between two cities using BFS in java

我試圖建立一個數據結構來存儲地圖內容,例如道路和城市信息。 我正在使用頂點/城市的鏈表,當創建一個頂點/城市時,它將在其構造函數中創建另一個邊鏈表。 我需要一種算法來找到兩個隨機城市之間的最短路徑。 我修改過的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表示“ to”是與此邊緣連接的城市名稱。

您應該在問題中說“ c”是靜態變量,並且它是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類,然后添加一個新類。 將該類稱為“城市”。 此類的實例應將城市名稱存儲為字符串和類型為City的數組。 在此數組中,指代您可以通過一條道路,一輛公共汽車甚至是步行從this城市出發的所有城市。

下一步是創建City類的實例,直到您在領土上創建了該國家的所有城市並將它們全部存儲在一個數組中為止。 如果您想將此數組稱為“ c”,則可以使用。 當然,我了解此數組是靜態的這一點非常重要,因此您將能夠在許多其他函數中使用它。

現在,您需要一個函數,該函數接收字符串的一個參數(即城市的名稱),並從靜態數組中返回對該名稱的City實例的引用。

實現此功能非常簡單。 您只需要for循環(遍歷所有城市),然后檢查for循環中當前城市的名稱是否與string參數匹配。 如果是,則在for循環中返回當前城市的參考,該功能將自動停止。 如果找不到使用該名稱的城市,則該函數當然會返回null。

您可以通過名稱“ findCityByName”來調用此函數。

完成此函數后,下一步是將getPath函數從“ getPath”重命名為“ getPaths”(只需添加以在's字母末尾添加),然后將此函數的返回類型從void更改為Boolean 此更改是好的,因為此函數的返回值將通知您該函數是成功還是失敗。 如果輸入參數無效,該函數將失敗並返回false 否則函數成功並返回true

現在添加三個附加的非常必要的參數,以使此功能正常工作。

此函數的前兩個參數仍然是兩個城市的兩個名稱,您要像在問題中所張貼的那樣將其作為字符串輸入,但是第三個參數應該是City類型的列表。 此列表存儲對所有訪問過的城市的引用。 您可以通過名稱“ visited”來訪問此參數。 您的錯誤是將“ visited”定義為局部變量,而不是parameter

第四個參數也應該是一個列表,但必須是City類型的array類型。 此列表中的每個數組存儲對您必須先走的所有城市的引用,然后才能從外出的城市到達目標城市。 此列表中的每個數組實際上都是一個路徑。 該列表包含從“ from”城市到達目標城市的所有可能路徑,其名稱在此函數的前兩個參數中指定為字符串。 該列表實際上包含您期望從此功能獲得的內容。

您可以通過名稱“路徑”來調用此參數。

第五個最后一個參數也應該是城市類型的列表,就像第三個參數的類型-“已訪問”一樣,但是此列表存儲了對已訪問城市的引用,但並不存儲 所有不像“已訪問”列表參數中的城市。 這是“已訪問”列表參數與該參數之間的差異。 每次對getPaths函數的調用結束時,都會刪除此列表的最后一個元素,這與“ visited”列表參數中不同。 “已訪問”列表將城市引用添加到其自身。 它永遠不會刪除它們,但是最后一個參數中的列表會刪除它們。

您可以使用其他名稱“ currentPath”來調用此參數。

請注意,您必須多次在此功能內調用此功能 ,才能正常工作!

此函數必須是遞歸的!

這些都是該函數的所有參數,但是始終要傳遞最后三個附加參數(第3、4和5)作為參考,而不是作為副本,這非常重要!!!

如果您將這些參數作為副本傳遞,則該功能將無法正常工作。

現在,終於讓我們開始重寫該函數的實現代碼。

首先,調用“ findCityByName”函數兩次,以獲取用於查找城市之間所有可能路徑的城市。 如果其中之一或兩者均為null ,則return false立即停止功能,因為您無法計算兩個都不存在或兩個都不存在的城市之間的路徑! 該功能也會失敗,因為前兩個參數之一或兩者均無效!

如果兩個都不為空,那么兩個城市都存在,那么您可以開始循環訪問“出發”城市數組中的所有城市。

如果for循環中的當前城市是您要前往的目標城市,請分配一個大小為“ currentPath”列表的新數組,並將“ currentPath”列表中的所有引用復制到該數組中,然后將其添加到“路徑”列表並返回true以立即停止當前函數,因為找到了路徑,並且參數對於當前getPath函數也有效。

否則(如果for循環中的當前城市不是目標城市,則)將for循環中當前城市的引用添加到“ visited”和“ currentPath”列表中,並調用 getPaths函數並在第一個參數中輸入名稱for循環中當前城市的位置。 在第二,第三,第四和第五個參數中,分別輸入當前調用的getPaths函數的第二,第三,第四和第五個參數(從標題中選取)。 仍然不要忘記將第3,第4和第5參數作為引用傳遞,而不是將副本或函數傳遞不起作用!

我在else語句中告訴您要做的所有事情只有在“已訪問”列表中尚未包含對for循環中當前城市的引用時,才會發生! 否則,循環繼續到下一個城市。 重要的是先檢查一下。

最后(在for循環之后),如果“ currentPath”不為空,則僅從 “ currentPath”中刪除最后一個引用, 也不要從“ visited”中刪除最后一個引用!!!

然后return true 第一次調用getPaths函數的前兩個參數有效。 功能可能會成功。

這就是getPaths函數的所有聲明,定義和實現。

請注意,每次調用此函數之前,必須為該函數在最后三個參數中獲得的三個列表分配內存。 在通過引用此函數傳遞這些列表之前,請通過空的構造函數,沒有參數的構造函數或首先將新列表初始化為空的構造函數分配它們。 這在第一次調用getPaths函數時非常重要,該函數全部列出了最后三個參數為空。

當對getPaths函數的第一次調用結束並且該函數成功執行時,只有“ currentPath”將保持為空。 否則,只有“已訪問” 不會保留為空。 如果函數成功,並且至少找到一條路徑,則“路徑”將填充數據。 只有“路徑”很有趣,其他兩個都不有趣,因為這是getPaths函數給出的答案。

准備好該路徑列表之后,現在您需要通過以該列表的大小分配一個新的數組,並將其轉換為City的大型數組,然后從該列表中復制所有對該數組的引用。

假數組是一個數組,它的類型也是數組。

現在讓我們定義一個新函數:getShortestPath

此函數僅接收雜散的City數組的一個參數,並返回City數組。

實際上,它接收路徑並返回最短路徑。 實現此功能的算法非常簡單。

首先定義新的局部變量:名稱為“ minSize”,然后鍵入int並將其分配給模擬數組中第一個數組的大小。

然后定義另一個新的局部變量:名稱為“ shortestPath”,並鍵入“ City的數組”,並將其設置為裝滿的數組中第一個數組的引用。

然后for循環其余數組(從第二個數組開始到最后一個數組),如果當前數組的大小小於“ minSize”的值,則將兩個“ minSize”都設置為for中當前數組的大小循環和“ shortestPath”到for循環中當前數組的引用。

最后,在for循環之后,返回“ shortestPath”。

如果您有許多城市,並且getPaths工作時間過多,則可以將位置添加到City類中(X和Y坐標為雙精度)。

然后刪除或注釋getShortestPath函數,並將函數getPaths從“ getPaths”重命名為“ getShortestPath”,然后刪除或注釋“ paths”參數以及與此參數有關的所有代碼。 還將參數“ currentPath”的名稱更改為“ path”,並將此更改應用於函數中的所有匹配項。

還要在if語句中添加另一個AND條件,該條件是for循環中的else語句。 在其他條件下,檢查for循環中的當前城市是否最接近目標城市。 要知道您需要先在for循環之前向“ from”數組中的所有城市添加另一個for循環,請計算所有這些城市到目標城市的距離並將其添加到您之前分配的新雙打本地列表中。 然后聲明,定義和實現一個函數,該函數返回雙精度數列表中的最小雙精度數。 然后調用此函數以獲取最近的城市到目標城市的距離,並將其保留在新的本地變量中:名稱“ min”並鍵入double

在附加條件下,如果當前城市到目標城市的計算距離近似等於“ min”的值,則當前城市是最接近目標城市的城市。

還定義,聲明和實現一個新函數,該函數接收City的兩個參數並將它們之間的距離返回為兩倍,並使用此函數來幫助您。

計算兩點距離的數學表達式為:

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函數中(曾經被稱為“ getPaths”調用)刪除或注釋了所有從“ path”(曾經被稱為“ currentPath”調用)中刪除元素的行。

在調用getShortestPath函數之前,新分配的列表路徑為空,但是在調用之后以及通過引用傳遞它之后,將填充數據“ path”。 它應該是“從”城市到“到”城市之間的最短路徑。

發表評論,告訴我您是否也了解C#,不僅Java。

我知道C#,所以如果您告訴我是,那么我會將代碼發布到C#中。

就這些。 我希望這回答了你的問題。 嘗試這個想法,並發表評論以告訴我是否有幫助。

我祝你好運! :d

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM