A Star算法是一智能找最短路徑算法(下面簡稱A算法), 與 Dijkstra算法相比,A算法訪問的節點比較少,因此可以縮短搜索時間。他的算法思想是:
這里有公式f
最終路徑長度f = 起點到該點的已知長度h + 該點到終點的估計長度g。
O表(open):
待處理的節點表。
C表(close):
已處理過的節點表。
算法流程:
1. 從起點開始,起點的f = 1 + g, 1表示此節點已走過的路徑是1,g是此節點到終點的估計距離, 放入鏈表O中。
可以假設g值的計算使用勾股定理公式來計算此點到終點的直線距離。
2. 當O不為空時,從中取出一個最小f值的節點x。
3.如果x等於終點,找到路徑,算法結束。否則走第4步.
4. 遍歷x的所有相鄰點,對所有相鄰點使用公式f,計算出f值后,
先檢查每個相鄰節點y是否在鏈表O和C中,
如果在O中的話的話,更新y節點的f值,保留最小的f值,
如果在C中的話,並且此時f值比C中的f值小,則更新f值,將y節點從C中移到O中。否則不做操作。
如果不在以上兩表中,按最小順序排序將y插入鏈表O。最后將x插入C表中。
例如:
起點是 (1,1), 終點是(5,5), 取一個相鄰點(0,1), 這時這個點的h=1+1 = 2, g可以用勾股定理公式來計算此點到終點的直線距離,就是 (5-0)*(5-0) - (5-1) *(5-1) = 9, 再開平方等於3,這樣f就等於2+3 = 5.然后將此點插入鏈表O中。
如果相鄰點不是路徑,比如是障礙,那就跳過。
5.繼續2,3,4步直到找到終點, 或者直到O為空表示沒找到路徑。
上面檢查O和C表的原因是:
如果圖是一個不規則的圖,比如一個游戲里,有幾個傳送門,這樣同一個點如果經過傳送門的話,路徑會大大縮短,這樣就需要檢查O和C表來更新f值,如果是一個不包含捷徑(傳送門)的圖,那樣就可以用個數組來標記已訪問過的節點,這樣就可以不用C表,也不用檢查O表來更新f值。
對於沒找到路徑的結果,訪問的節點有可能差不多是所有節點,這樣的效率和Dijkstra一樣低,我們可以使用同時從兩端用A算法來找路徑,這樣當其中一個沒找到路徑的話,尋找結束。這樣用的時間將是2 * min(S,E)的時間,S是從起點開始尋路徑的時間,E是從終點開始尋路徑的時間。這樣的一個典型的例子是
終點是個孤立的點,沒有任何點能到達他,而其他點都是鏈接的,那么如果光從起點開始找的話,要到訪問完所有除終點之外的點后才知道找不到終點。這樣的效率非常差。 如果同時從兩端開始找,馬上就能知道終點沒有任何路徑相鄰,尋找結束。
當然從終點反找起點的算法有限制,比如有向圖就無法適用。
兩端同時查找的算法需要有些改動:
在第3步時,如果是S端的查找過程,則檢查x是否存在E端查找過程的C表里,如果存在,則查找到路徑。將兩個過程已訪問的路徑合並則是結果。反過來E端的查找過程也一樣比較處理。
我用Qt寫了一個例子來檢驗A算法,這里不好附上程序,就附上幾張圖
Dijkstra搜索的節點圖
同樣一張圖,A Star算法搜索的節點圖