1. 程式人生 > >A*演算法(A星演算法)DFS BFS

A*演算法(A星演算法)DFS BFS

BFS演算法過程:

1.取出佇列首元素作為當前節點,檢查是否為目的地。

2.對當前點進行展開,檢查是否與佇列重複,依次進入佇列。

3.當隊首指標與隊尾指標重合時,表示所有路徑已經探索完畢。

優點:獲得最短路徑(探索深度而不是權值)

缺點:極為巨大的記憶體需求(能夠高達幾十MB)造成程式堆疊溢位。

DFS演算法過程:

1.展開當前節點,若無法展開則退回父節點,並且出棧。

2.檢查子結點中是否有目的地。

3.依次進入子結點,子結點入棧。

優點:節省空間,得到最短路徑。

缺點:時間複雜度高,不一定是最佳的結果。

/*

1968年,的一篇論文,“P. E. Hart, N. J. Nilsson, and B. Raphael. A formal basis for the heuristic determination of minimum cost paths in graphs. IEEE Trans. Syst. Sci. and Cybernetics, SSC-4(2):100-107, 1968”。從此,一種精巧、高效的演算法------A*演算法橫空出世了,並在相關領域得到了廣泛的應用。

A*搜尋演算法俗稱A星演算法。這是一種在圖形平面上,有多個節點的路徑,求出最低通過成本的演算法。常用於遊戲中的NPC的移動計算,或線上遊戲的BOT的移動計算上。

*/

A*演算法是在最短路徑型別的題目中出現的,通常同時出現的解決方法還有Dijkstra演算法,BFS演算法,DFS演算法。在盲目搜尋中使用後三者的平率較高,但是在時間複雜度較低的啟發式搜尋中A*演算法能夠具有目的性,選擇性的朝向目標前進。

A* 演算法(轉載自結構之法_演算法之道http://blog.csdn.net/v_JULY_v/article/details/6238029 榮耀屬於v_July_v)

Dijkstra 演算法(轉載自結構之法_演算法之道http://blog.csdn.net/v_JULY_v/article/details/6238029 榮耀屬於v_July_v)

 

很明顯從此看出A*演算法帶來的時間上空間上的節省(相對複雜度適當的啟發式函式)。

下面開始介紹A*演算法的原理(個人簡單理解和闡釋):

具有適合的啟發式函式f(n)=g(n)+h(n),具有能夠在一定範圍內保證正確指向目標的正確度,具有較小的時間空間複雜度。g(n)表示從起點到此處的代價(包括探索的深度和圖中的權值)。h(n)表示啟發式函式計算得到的模擬值。按照通常的理解,當只具有g(n)的尋路演算法的時候,一般是Dijkstra演算法。不具有優化函式的尋路演算法則是BFS和DFS。

個人原創A*演算法過程:

1.從open表中取出h(n)最大的節點作為當前節點。如果是目標節點,則成功。如果open表為空,則演算法失敗。

2.探索當前節點所能達到的所有節點,更新open表,並將當前節點移動到close表。

個人對A*的一些看法:

按照很多講解的文章上看,對於優先佇列每次更新都要進行一次排序,但是每次取出的總是最大的那個節點。雖然如果不使用優先佇列,在移動節點的時候會耗費大量的複雜度。

以下(轉載自演算法驛站http://blog.programfan.com/article.asp?id=18471榮耀屬於rickone)

八數碼難題,一個A*的好例子。
問題描述為有這樣一個3*3方陣格子:

格子上有1-8八個數字外加一個空格,每次只能把與空格相臨的一個數字移到空格內,移動一次算作一步,給出初始狀態和目標狀態,求如何以最少的步數完成移動?

設計A*演算法時,g(n)就取當前已移動的步數,h(n)取各個數字到目標狀態中對應數字的位置的最短距離之和,這樣選取的原因是,對於每一次移動,只能使一個數字改變一個相臨位置,所以h(n)步是至少需要的,所以滿足h(n)<=h*(n)。

A*的成功之處就是在選擇好的h(n),如果實在沒辦法令它為0也是可以求得問題的解的。