算法,就是(結合各種數學知識)解決問題的有限步驟,可以表現為程序、流程圖。
假設要尋找一條路徑,從起點S,終點G。
有幾個關鍵原則:
1. 路徑的下一個節點,不能和以往節點相同,否則會造成死循環。
2. 所有“待選”,“待算”路徑,放在一個列表中;
OK,現在可以假設,有基礎數據,各個點的坐標:
struct Point {
char ID;
double x;
double y;
}
各個可走路徑的長度
struct distance
{
char Id1;
char id2;
double lenght;
}
那么,我們想要的結果,是:
struct Path {
List<int> Ids; //一個有序的節點集合
}
british museum算法
這個算法,說白了就是構造一顆樹,沒什么目的的構造,造到死胡同為止,最后看看那條包含S和G
要實現這個算法,需要兩個列表,一個存放所有走到死胡同的路徑R,一個存放還沒走到死胡同的路徑T。
被划去的路徑,例如:在上一步演變到下一步中划去的。
算法開始:
1. T:(S) R:空
2. T:(S,A),(S,B) R:空
3. T:(S,A,B),(S,A,D),(S,B) R:空
4. T:(S,A,B,C),(S,A,D),(S,B) R:空
5. T:(S,A,B,C,E),(S,A,D),(S,B) R:空
6. T:(S,A,D,G),(S,B) R:(S,A,B,C,E)
7. T:(S,B,A),(S,B,C) R:(S,A,B,C,E),(S,A,D,G)
8. T:(S,B,A,D),(S,B,C) R:(S,A,B,C,E),(S,A,D,G)
9. T:(S,B,A,D,G),(S,B,C) R:(S,A,B,C,E),(S,A,D,G)
10. T:(S,B,C,E) R:(S,A,B,C,E),(S,A,D,G),(S,B,A,D,G)
11. T:空 R:(S,A,B,C,E),(S,A,D,G),(S,B,A,D,G),(S,B,C,E)
12. 看看R中那條路徑含有S和G,S到G的距離那條最短即可。
偽代碼:
while(T.Count > 0)
{
if ( T[0]的最后一個節點不是G && 能T[0]的下一個節點 的數目n > 0 )
復制n個T[0],然后分別往后邊添加可添加的節點;
移除T的第0個元素;
將新的n個隊列插入到T的前面;
else
將T的第0個元素放進R;
移除T的第0個元素;
}
deepth first(深度優先)算法
和british museum算法不同的地方是:1. 不需要結果列表;2. 發現目標馬上停下來;3. 有回溯
缺點:不能總是發現最優路徑
1. T:(S)
2. T:(S,A),(S,B)
3. T:(S,A,B),(S,A,D),(S,B)
4. T:(S,A,B,C),(S,A,D),(S,B)
5. T:(S,A,B,C,E),(S,A,D),(S,B)
6. T:(S,A,D,G),(S,B)
偽代碼:
while(T.Count>0)
{
if ( 能T[0]的下一個節點 的數目n > 0 )
if (能加在T[0]后的節點有G)
返回T[0] + G的路徑
else
復制n個T[0],然后分別往后邊添加可添加的節點;
移除T的第0個元素
將新的n個隊列插入到T的前面(這個是算法最要特點)
else
移除T的第0個元素
}
breadth first(廣度優先)算法
和british museum算法不同的地方是:1. 實現上將擴展后的路徑,放到列表后邊;2. 沒回溯
比深度優先的優點是,更早發現路徑淺的路線,雖然本例子是同一個,但難保“右”邊出現G比較快。
缺點:較“淺”的不一定是路徑最短的。
1. T:(S)
2. T:(S,A),(S,B)
3. T:(S,B),(S,A,B),(S,A,D)
4. T:(S,A,B),(S,A,D),(S,B,A), (S,B,C)
5. T:(S,A,D),(S,B,A), (S,B,C),(S,A,B,C)
6. T:(S,B,A), (S,B,C),(S,A,B,C),(S,A,D,G)
breadth first(廣度優先)算法的優化
以上,無論哪個算法,都會對同一節點考慮多次,例如:
那么,優化的地方是,考慮過的節點不再考慮,變為:
1. T:(S)
2. T:(S,A),(S,B)
3. T:(S,B),(S,A,D)
4. T:(S,A,D), (S,B,C)
5. T:(S,B,C),(S,A,D,G)
在實現上,對比廣度算法,只需要在添加到列表后邊前,去除部分不再考慮的節點。
hill climing算法:在深度優先的基礎上改進
有不斷擴展節點,回溯,使用啟發信息的特點
特點:在深度優先的基礎上,只考慮離目標直線距離最近的節點。
區別: 在將新的路線插入隊列前,先根據離目標的距離,按升序排列。
缺點:這種是一種比較“短視”的算法。
優點:如果路網太復雜的話,效果可能更好
1. T:(S)
2. T:(S,B),(S,A) (這里發生了排序)
3. T:(S,B,C),(S,B,A),(S,A) (這里發生了排序)
4. T:(S,B,C,E),(S,B,A),(S,A)
5. T:(S,B,A,D),(S,A)
6. T:(S,B,A,D,G),(S,A)
束搜索:廣度優先的改良,使用“知情啟發信息”
區別:1. 在廣度優先中,限制每一層中考慮的路徑數量w;2. 節點重復的不考慮;3. 將距離教小的值放到隊列前面
關鍵:設置好w值
1. T:(S)
2. T:(S,B) ,(S,A) //B點比A點近
3. T:(S,A),(S,B,C)
4. T:(S,B,C),(S,A,D)
5. T:(S,A,D) ,(S,B,C,E)
6. T:(S,A,D,G)
偽代碼:
while(T.Count>0)
{
if ( 能T[0]的下一個節點 的數目n > 0 )
if (能加在T[0]后的節點有G)
返回T[0] + G的路徑;
else
移除n個節點中,在路徑已經出現過節點
復制 ≤ n個T[0],然后分別往后邊添加可添加的節點;
移除T的第0個元素;
對 ≤ n個T[0]延伸路徑,根據最后一個節點對G點的距離,按升序排列,並取前w個T[0]的延伸路徑;(這個是算法主要特點)
將新w個T[0]的延伸路徑插入到T的后面(這個是算法主要特點)
else
移除T的第0個元素
}
搜索辦法 | 回溯 | 節點擴展 | 使用啟發式信息 | 擴展路徑插入方式 |
british museum | false | false | false | |
深度優先(deepth first) | true | true | false | 前 |
廣度優先(breath first) | false | true | false | 后 |
爬山算法(hill climing) | true | true | true | 前 |
束搜素 | false | false | true | 后 |
*節點擴展,在實現上,將新的擴展路徑加入到隊列的前面;思想上,是否對新的擴展路徑“一路走到黑”
*回溯,在實現上,將新的擴展路徑加入到隊列的前面;新的路徑走到死胡同后,及時丟棄;
*啟發式信息,是否使用坐標值來優化