尋路算法之A*算法


A*算法是用於尋找兩點之間的最短路徑,同時它也是一種靜態路網中求解最短路最有效的直搜索方法,公式f(n)=h(n)+g(n)給出了鄰居節點到目標節點所需要的總消耗成本,h(n)是當前節點到該鄰居節點的所消耗的成本,g(n)是該鄰居節點到目標節點的估計消耗成本,比較常用的估計方法是歐幾里得方法和曼哈頓方法。

A*算法首先要准備兩個列表,一個開啟列表,一個關閉列表,開啟列表存儲還未走的節點(但不是一開始就把所有節點加入開啟列表),關閉列表存儲走過的節點,將起始節點加入到開啟列表,在開啟列表不為空時,取出開啟列表中最小消耗成本的節點,判斷是否是目標節點,是就直接結束A*,取得它的周圍鄰居節點(通常是8個),判斷鄰居節點是否在關閉列表中,在關閉列表中,不做處理,不在關閉列表中,再判斷是否在開啟列表中,若已在開啟列表中,計算它的f(n),是否比以前的f(n)小,小就更新它的f(n)並將它的父節點設為當前節點。大的話就不做處理,若不在開啟列表中,計算它的f(n),更新f(n)將父節點設為當前節點。處理完它的周圍鄰居節點后,一輪循環結束,再移除開啟列表中的當前節點,放在關閉列表中,因為已經走過這個節點。然后在開啟列表不為空時繼續上述循環,直到找到目標節點,或者找遍所有節點都找不到目標節點。C++代碼如下(相關函數並未實現,視實際情況而定):

 1 typedef struct node
 2 {
 3 float currentCost;//h(n)
 4 float toTalCost;//f(n)
 5 node * parent;//父節點
 6 }Node;
 7 Vector<Node>  OpenList;//開啟列表
 8 Vector<Node>  CloseList;//關閉列表
 9 
10 Node  AStar(Node start,Node Goal){
11   OpenList.Add(start);
12   while(OpenList.Length!=0)
13 {
14       Node* minNode=  OpenLIst.Min();//Min()選出最小消耗成本節點
15       if(minNode == Goal)
16 {
17 return minNode;
18 }
19        Vector<Node> Neighbors;//鄰居列表
20          GetNeighBors(Neighbors,minNode);/*得到最小消耗成本節點的周圍鄰居節點*/
21            for(int i=0;i<NeighBors.Count;i++)
22 {
23          if(Neighbors[i].obstacle)//如果鄰居節點被標志障礙物,跳過。
24 {
25 continue;/*也可以在GetNeighBors函數里進行處理,障礙物節點不加入鄰居列表*/
26 }
27 if(CloseList.Contain(Neighbors[i]))//節點已經走過不作處理
28 continue;
29 float currentCost=CacluateDistance(minNode,Neighbors[i])+minNode.currentCost;
30 float totalCost = currentCost+CacluateDistance(Neighbors[i],Goal);
31 if(OpenList.Cotain(Neighbors[i]))//如果開啟列表包含該鄰居節點
32 {
33 
34 if(totalCost<Neighbors[i].totalCost)
35 {
36 Neighbors[i].totalCost=totalCost;
37 Neighbors[i].currentCost =currentCost;
38 Neighbors[i].parent=minNode;
39 }
40 }
41 else
42 {
43 Neighbors[i].totalCost=totalCost;
44 Neighbors[i].currentCost =currentCost;
45 Neighbors[i].parent=minNode;
46 }
47 }
48 OpenList.Remove(minNode);
49 CloseList.Add(minNode);
50  }
51 return NULL;//找不到目標節點,返回空
52 }

若成功返回一個節點,那么可以不斷往回迭代父節點得到一條逆向的最短路徑。A*的思想是為每個節點都估價消耗成本(沿當前所走的路徑到目標節點的消耗成本),選擇最小消耗成本的節點優先計算,就使節點搜索沿目標節點那邊搜索,也被稱之為啟發式搜索。而開啟列表得到最小的消耗成本節點或添加節點,應該用二叉堆(最小堆)插入,這樣取最小節點時間復雜度為O(1),添加節點時間復雜度為O(log(n)),比另一種遍歷取節點O(n),加節點O(1)好一些。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM