小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

一之續(xù)、A*,Dijkstra,BFS算法性能比較及A*算法的應(yīng)用

 學(xué)海無(wú)涯GL 2014-01-26

                    一之續(xù)、A*,Dijkstra,雙向BFS算法性能比較及A*算法的應(yīng)用


作者:July   二零一一年三月十日。
出處:http://blog.csdn.net/v_JULY_v
-------------------------------------------------- 

引言:
    最短路徑的各路算法A*算法、Dijkstra 算法BFS算法,都已在本BLOG內(nèi)有所闡述了。其中,Dijkstra 算法,后又寫了一篇文章繼續(xù)闡述:二(續(xù))、理解Dijkstra算法。但,想必,還是有部分讀者對(duì)此類最短路徑算法,并非已了然于胸,或者,無(wú)一個(gè)總體大概的印象。

    本文,即以演示圖的形式,比較它們各自的尋路過(guò)程,讓各位對(duì)它們有一個(gè)清晰而直觀的印象。
    我們比較,以下五種算法:
        1. A* (使用曼哈頓距離)
        2. A* (采用歐氏距離)
        3. A* (利用切比雪夫距離)
        4. Dijkstra
        5. Bi-Directional Breadth-First-Search(雙向廣度優(yōu)先搜索)

    咱們以下圖為例,圖上色方塊代表起始點(diǎn),色方塊代表目標(biāo)點(diǎn),色的方塊代表障礙物,白色的方塊代表可以通行的路徑。
    下面,咱們隨意擺放起始點(diǎn)綠塊,目標(biāo)點(diǎn)紅塊的位置,然后,在它們中間隨便畫一些障礙物,
    最后,運(yùn)行程序,比較使用上述五種算法,得到各自不同的路徑,各自找尋過(guò)程中所覆蓋的范圍,各自的工作流程,并從中可以窺見(jiàn)它們的效率高低。


A*、Dijkstra、BFS算法性能比較演示:
    ok,任意擺放綠塊與紅塊的三種狀態(tài)(演示工具來(lái)源:http://code.google.com/p/mycodeplayground/):
一、起始點(diǎn)綠塊,與目標(biāo)點(diǎn)紅塊在同一條水平線上:


各自的搜尋路徑為:
        1. A* (使用曼哈頓距離)

        2. A* (采用歐氏距離)

        3. A* (利用切比雪夫距離)

        4. Dijkstra 算法.//很明顯,Dijkstra 搜尋效率明顯差于上述A* 算法。(看它最后找到目標(biāo)點(diǎn)紅塊所走過(guò)的路徑,和覆蓋的范圍,即能輕易看出來(lái),下面的比較,也是基于同一個(gè)道理。看路徑,看覆蓋的范圍,評(píng)價(jià)一個(gè)算法的效率)。

 

       5. Bi-Directional Breadth-First-Search(雙向廣度優(yōu)先搜索) 

 

二、起始點(diǎn)綠塊,目標(biāo)點(diǎn)紅塊在一斜線上:

各自的搜尋路徑為:
        1. A* (使用曼哈頓距離)

        2. A* (采用歐氏距離)

        3. A* (利用切比雪夫距離)

        4. Dijkstra 算法。 //與上述A* 算法比較,覆蓋范圍大,搜尋效率較低。

 

        5. Bi-Directional Breadth-First-Search(雙向廣度優(yōu)先搜索)

 

三、起始點(diǎn)綠塊,目標(biāo)點(diǎn)紅塊被多重障礙物阻擋:

各自的搜尋路徑為(同樣,還是從綠塊到紅塊):
        1. A* (使用曼哈頓距離)

        2. A* (采用歐氏距離)..

        3. A* (利用切比雪夫距離)

        4. Dijkstra....

        5. Bi-Directional Breadth-First-Search(雙向廣度優(yōu)先搜索) //覆蓋范圍同上述Dijkstra 算法一樣很大,效率低下。


A*搜尋算法的高效之處
      如上,是不是對(duì)A*、Dijkstra、雙向BFS算法各自的性能有了個(gè)總體大概的印象列?由上述演示,我們可以看出,在最短路徑搜尋效率上,一般有A*>Dijkstra、雙向BFS,其中Dijkstra、雙向BFS到底哪個(gè)算法更優(yōu),還得看具體情況。
      由上,我們也可以看出,A*搜尋算法的確是一種比較高效的尋路算法。

      A*算法最為核心的過(guò)程,就在每次選擇下一個(gè)當(dāng)前搜索點(diǎn)時(shí),是從所有已探知的但未搜索過(guò)點(diǎn)中(可能是不同層,亦可不在同一條支路上),選取f值最小的結(jié)點(diǎn)進(jìn)行展開(kāi)。
      而所有“已探知的但未搜索過(guò)點(diǎn)”可以通過(guò)一個(gè)按f值升序的隊(duì)列(即優(yōu)先隊(duì)列)進(jìn)行排列。
      這樣,在整體的搜索過(guò)程中,只要按照類似廣度優(yōu)先的算法框架,從優(yōu)先隊(duì)列中彈出隊(duì)首元素(f值),對(duì)其可能子結(jié)點(diǎn)計(jì)算g、h和f值,直到優(yōu)先隊(duì)列為空(無(wú)解)或找到終止點(diǎn)為止。

      A*算法與廣度、深度優(yōu)先和Dijkstra 算法的聯(lián)系就在于當(dāng)g(n)=0時(shí),該算法類似于DFS,當(dāng)h(n)=0時(shí),該算法類似于BFS。且同時(shí),如果h(n)為0,只需求出g(n),即求出起點(diǎn)到任意頂點(diǎn)n的最短路徑,則轉(zhuǎn)化為單源最短路徑問(wèn)題,即Dijkstra算法。這一點(diǎn),可以通過(guò)上面的A*搜索樹(shù)的具體過(guò)程中將h(n)設(shè)為0或?qū)(n)設(shè)為0而得到。

BFS、DFS與A*搜尋算法的比較
    參考了算法驛站上的部分內(nèi)容:
    不管以下論述哪一種搜索,都統(tǒng)一用這樣的形式表示:搜索的對(duì)象是一個(gè)圖,它面向一個(gè)問(wèn)題,不一定有明確的存儲(chǔ)形式,但它里面的一個(gè)結(jié)點(diǎn)都有可能是一個(gè)解(可行解),搜索的目的有兩個(gè)方面,或者求可行解,或者從可行解集中求最優(yōu)解。
    我們用兩張表來(lái)進(jìn)行搜索,一個(gè)叫OPEN表,表示那些已經(jīng)展開(kāi)但還沒(méi)有訪問(wèn)的結(jié)點(diǎn)集,另一個(gè)叫CLOSE表,表示那些已經(jīng)訪問(wèn)的結(jié)點(diǎn)集。

蠻力搜索(BFS,DFS)
BFS(Breadth-First-Search 寬度優(yōu)先搜索)
  首先將起始結(jié)點(diǎn)放入OPEN表,CLOSE表置空,算法開(kāi)始時(shí):
    1、如果OPEN表不為空,從表中開(kāi)始取一個(gè)結(jié)點(diǎn)S,如果為空算法失敗
    2、S是目標(biāo)解嗎?是,找到一個(gè)解(繼續(xù)尋找,或終止算法);不是到3
    3、將S的所有后繼結(jié)點(diǎn)展開(kāi),就是從S可以直接關(guān)聯(lián)的結(jié)點(diǎn)(子結(jié)點(diǎn)),如果不在CLOSE表中,就將它們放入OPEN表末尾,而把S放入CLOSE表,重復(fù)算法到1。

DFS(Depth-First-Search 深度優(yōu)先搜索)
  首先將起始結(jié)點(diǎn)放入OPEN表,CLOSE表置空,算法開(kāi)始時(shí):
    1、如果OPEN表不為空,從表中開(kāi)始取一個(gè)結(jié)點(diǎn)S,如果為空算法失敗
    2、S是目標(biāo)解嗎?是,找到一個(gè)解(繼續(xù)尋找,或終止算法);不是到3
    3、將S的所有后繼結(jié)點(diǎn)展開(kāi),就是從S可以直接關(guān)聯(lián)的結(jié)點(diǎn)(子結(jié)點(diǎn)),如果不在CLOSE表中,就將它們放入OPEN表開(kāi)始,而把S放入CLOSE表,重復(fù)算法到1。

是否有看出:上述的BFS和DFS有什么不同?
    仔細(xì)觀察OPEN表中待訪問(wèn)的結(jié)點(diǎn)的組織形式,BFS是從表頭取結(jié)點(diǎn),從表尾添加結(jié)點(diǎn),也就是說(shuō)OPEN表是一個(gè)隊(duì)列,是的,BFS首先讓你想到‘隊(duì)列’;而DFS,它是從OPEN表頭取結(jié)點(diǎn),也從表頭添加結(jié)點(diǎn),也就是說(shuō)OPEN表是一個(gè)棧!

    DFS用到了棧,所以有一個(gè)很好的實(shí)現(xiàn)方法,那就是遞歸,系統(tǒng)棧是計(jì)算機(jī)程序中極重要的部分之一。用遞歸也有個(gè)好處就是,在系統(tǒng)棧中只需要存結(jié)點(diǎn)最大深度那么大的空間,也就是在展開(kāi)一個(gè)結(jié)點(diǎn)的后續(xù)結(jié)點(diǎn)時(shí)可以不用一次全部展開(kāi),用一些環(huán)境變量記錄當(dāng)前的狀態(tài),在遞歸調(diào)用結(jié)束后繼續(xù)展開(kāi)。

利用系統(tǒng)棧實(shí)現(xiàn)的DFS
函數(shù) dfs(結(jié)點(diǎn) s)
{
      s超過(guò)最大深度了嗎?是:相應(yīng)處理,返回;
      s是目標(biāo)結(jié)點(diǎn)嗎?是:相應(yīng)處理;否則:
      {
            s放入CLOSE表;
            for(c=s.第一個(gè)子結(jié)點(diǎn) ;c不為空 ;c=c.下一個(gè)子結(jié)點(diǎn)() )
                  if(c不在CLOSE表中)
                        dfs(c);遞歸
      }
}

    如果指定最大搜索深度為n,那系統(tǒng)棧最多使用n個(gè)單位,它相當(dāng)于有狀態(tài)指示的OPEN表,狀態(tài)就是c,在棧里存了前面搜索時(shí)的中間變量c,在后面的遞歸結(jié)束后,c繼續(xù)后移。在象棋等棋類程序中,就是用這樣的DFS的基本模式搜索棋局局面樹(shù)的,因?yàn)槿绻肙PEN表,有可能還沒(méi)完成搜索OPEN表就暴滿了,這是難于控制的情況。

    我們說(shuō)DFS和BFS都是蠻力搜索,因?yàn)樗鼈冊(cè)谒阉鞯揭粋€(gè)結(jié)點(diǎn)時(shí),在展開(kāi)它的后續(xù)結(jié)點(diǎn)時(shí),是對(duì)它們沒(méi)有任何‘認(rèn)識(shí)’的,它認(rèn)為它的孩子們都是一樣的‘優(yōu)秀’,但事實(shí)并非如此,后續(xù)結(jié)點(diǎn)是有好有壞的。好,就是說(shuō)它離目標(biāo)結(jié)點(diǎn)‘近’,如果優(yōu)先處理它,就會(huì)更快的找到目標(biāo)結(jié)點(diǎn),從而整體上提高搜索性能。

啟發(fā)式搜索
    為了改善上面的算法,我們需要對(duì)展開(kāi)后續(xù)結(jié)點(diǎn)時(shí)對(duì)子結(jié)點(diǎn)有所了解,這里需要一個(gè)估值函數(shù),估值函數(shù)就是評(píng)價(jià)函數(shù),它用來(lái)評(píng)價(jià)子結(jié)點(diǎn)的好壞,因?yàn)闇?zhǔn)確評(píng)價(jià)是不可能的,所以稱為估值。打個(gè)比方,估值函數(shù)就像一臺(tái)顯微鏡,一雙‘慧眼’,它能分辨出看上去一樣的孩子們的手,哪個(gè)很臟,有細(xì)菌,哪個(gè)沒(méi)有,很干凈,然后對(duì)那些干凈的孩子進(jìn)行獎(jiǎng)勵(lì)。這里相當(dāng)于是需要‘排序’,排序是要有代價(jià)的,而花時(shí)間做這樣的工作會(huì)不會(huì)對(duì)整體搜索效率有所幫助呢,這完全取決于估值函數(shù)。

    排序,怎么排?用哪一個(gè)?快排吧,qsort!不一定,要看要排多少結(jié)點(diǎn),如果很少,簡(jiǎn)單排序法就很OK了??淳唧w情況了。
    排序可能是對(duì)OPEN表整體進(jìn)行排序,也可以是對(duì)后續(xù)展開(kāi)的子結(jié)點(diǎn)排序,排序的目的就是要使程序有啟發(fā)性,更快的搜出目標(biāo)解。

    如果估值函數(shù)只考慮結(jié)點(diǎn)的某種性能上的價(jià)值,而不考慮深度,比較有名的就是有序搜索(Ordered-Search),它著重看好能否找出解,而不看解離起始結(jié)點(diǎn)的距離(深度)。
    如果估值函數(shù)考慮了深度,或者是帶權(quán)距離(從起始結(jié)點(diǎn)到目標(biāo)結(jié)點(diǎn)的距離加權(quán)和),那就是A*,舉個(gè)問(wèn)題例子,八數(shù)碼問(wèn)題,如果不考慮深度,就是說(shuō)不要求最少步數(shù),移動(dòng)一步就相當(dāng)于向后多展開(kāi)一層結(jié)點(diǎn),深度多算一層,如果要求最少步數(shù),那就需要用A*。
    簡(jiǎn)單的來(lái)說(shuō)A*就是將估值函數(shù)分成兩個(gè)部分,一個(gè)部分是路徑價(jià)值,另一個(gè)部分是一般性啟發(fā)價(jià)值,合在一起算估整個(gè)結(jié)點(diǎn)的價(jià)值。

    從A*的角度看前面的搜索方法,如果路徑價(jià)值為0就是有序搜索,如果路徑價(jià)值就用所在結(jié)點(diǎn)到起始結(jié)點(diǎn)的距離(深度)表示,而啟發(fā)值為0,那就是BFS或者DFS,它們兩剛好是個(gè)反的,BFS是從OPEN表中選一個(gè)深度最小的進(jìn)行展開(kāi),
    而DFS是從OPEN表中選一個(gè)深度最大的進(jìn)行展開(kāi)。當(dāng)然只有BFS才算是特殊的A*,所以BFS可以求要求路徑最短的問(wèn)題,只是沒(méi)有任何啟發(fā)性。 下文稍后,會(huì)具體談A*搜尋算法思想。

BFS、DFS、Kruskal、Prim、Dijkstra算法時(shí)間復(fù)雜度
      上面,既然提到了A*算法與廣度、深度優(yōu)先搜索算法的聯(lián)系,那么,下面,也順便再比較下BFS、DFS、Kruskal、Prim、Dijkstra算法時(shí)間復(fù)雜度吧:     
      一般說(shuō)來(lái),我們知道,BFS,DFS算法的時(shí)間復(fù)雜度為O(V+E),
      最小生成樹(shù)算法Kruskal、Prim算法的時(shí)間復(fù)雜度為O(E*lgV)。
      而Prim算法若采用斐波那契堆實(shí)現(xiàn)的話,算法時(shí)間復(fù)雜度為O(E+V*lgV),當(dāng)|V|<<|E|時(shí),E+V*lgV是一個(gè)較大的改進(jìn)。
            //|V|<<|E|,=>O(E+V*lgV) << O(E*lgV),對(duì)吧。:D
      Dijkstra 算法,斐波納契堆用作優(yōu)先隊(duì)列時(shí),算法時(shí)間復(fù)雜度為O(V*lgV + E)。
           //看到了吧,與Prim算法采用斐波那契堆實(shí)現(xiàn)時(shí),的算法時(shí)間復(fù)雜度是一樣的。

      所以我們,說(shuō),BFS、Prime、Dijkstra 算法是有相似之處的,單從各算法的時(shí)間復(fù)雜度比較看,就可窺之一二。


A*搜尋算法的思想
      ok,既然,A*搜尋算法作為是一種好的、高效的尋路算法,咱們就來(lái)想辦法實(shí)現(xiàn)它吧。
      實(shí)現(xiàn)一個(gè)算法,首先得明確它的算法思想,以及算法的步驟與流程,從我之前的一篇文章中,可以了解到:
      A*算法,作為啟發(fā)式算法中很重要的一種,被廣泛應(yīng)用在最優(yōu)路徑求解和一些策略設(shè)計(jì)的問(wèn)題中。
而A*算法最為核心的部分,就在于它的一個(gè)估值函數(shù)的設(shè)計(jì)上:

        f(n)=g(n)+h(n)

      其中f(n)是每個(gè)可能試探點(diǎn)的估值,它有兩部分組成:
一部分,為g(n),它表示從起始搜索點(diǎn)到當(dāng)前點(diǎn)的代價(jià)(通常用某結(jié)點(diǎn)在搜索樹(shù)中的深度來(lái)表示)。
另一部分,即h(n),它表示啟發(fā)式搜索中最為重要的一部分,即當(dāng)前結(jié)點(diǎn)到目標(biāo)結(jié)點(diǎn)的估值,

h(n)設(shè)計(jì)的好壞,直接影響著具有此種啟發(fā)式函數(shù)的啟發(fā)式算法的是否能稱為A*算法。

      一種具有f(n)=g(n)+h(n)策略的啟發(fā)式算法能成為A*算法的充分條件是:

 1、搜索樹(shù)上存在著從起始點(diǎn)到終了點(diǎn)的最優(yōu)路徑。
 2、問(wèn)題域是有限的。
 3、所有結(jié)點(diǎn)的子結(jié)點(diǎn)的搜索代價(jià)值>0。
 4、h(n)=<h*(n) (h*(n)為實(shí)際問(wèn)題的代價(jià)值)。

      當(dāng)此四個(gè)條件都滿足時(shí),一個(gè)具有f(n)=g(n)+h(n)策略的啟發(fā)式算法能成為A*算法,并一定能找到最優(yōu)解。
      對(duì)于一個(gè)搜索問(wèn)題,顯然,條件1,2,3都是很容易滿足的,而條件4: h(n)<=h*(n)是需要精心設(shè)計(jì)的,由于h*(n)顯然是無(wú)法知道的,所以,一個(gè)滿足條件4的啟發(fā)策略h(n)就來(lái)的難能可貴了。

      不過(guò),對(duì)于圖的最優(yōu)路徑搜索和八數(shù)碼問(wèn)題,有些相關(guān)策略h(n)不僅很好理解,而且已經(jīng)在理論上證明是滿足條件4的,從而為這個(gè)算法的推廣起到了決定性的作用。


A*搜尋算法的應(yīng)用
      ok,咱們就來(lái)應(yīng)用A*搜尋算法實(shí)現(xiàn)八數(shù)碼問(wèn)題,下面,就是其主體代碼,由于給的注釋很詳盡,就不再啰嗦了,有任何問(wèn)題,請(qǐng)不吝指正:

//節(jié)點(diǎn)結(jié)構(gòu)體
typedef struct Node
{
 int data[9];
 double f,g;
 struct Node * parent;
}Node,*Lnode;

//OPEN CLOSED 表結(jié)構(gòu)體
typedef struct Stack
{
 Node * npoint;
 struct Stack * next;
}Stack,* Lstack;

//選取OPEN表上f值最小的節(jié)點(diǎn),返回該節(jié)點(diǎn)地址
Node * Minf(Lstack * Open)
{
 Lstack temp = (*Open)->next,min = (*Open)->next,minp = (*Open);
 Node * minx;
    while(temp->next != NULL)
 {
  if((temp->next ->npoint->f) < (min->npoint->f))
  {
   min = temp->next;
   minp = temp;
  }
  temp = temp->next;
 }
 minx = min->npoint;
 temp = minp->next;
 minp->next = minp->next->next;
 free(temp);
 return minx;
}

//判斷是否可解
int Canslove(Node * suc, Node * goal)
{
 int a = 0,b = 0,i,j;
 for(i = 1; i< 9;i++)
  for(j = 0;j < i;j++)
  {
   if((suc->data[i] > suc->data[j]) && suc->data[j] != 0)
    a++;
   if((goal->data[i] > goal->data[j]) && goal->data[j] != 0)
    b++;
  }
  if(a%2 == b%2)
   return 1;
  else
   return 0;
}

//判斷節(jié)點(diǎn)是否相等 ,1相等,0不相等
int Equal(Node * suc,Node * goal)
{
 for(int i = 0; i < 9; i ++ )
  if(suc->data[i] != goal->data[i])return 0;
  return 1;
}

//判斷節(jié)點(diǎn)是否屬于OPEN表 或 CLOSED表,是則返回節(jié)點(diǎn)地址,否則返回空地址
Node * Belong(Node * suc,Lstack * list)
{
 Lstack temp = (*list) -> next ;
 if(temp == NULL)return NULL;
 while(temp != NULL)
 {
  if(Equal(suc,temp->npoint))return temp -> npoint;
  temp = temp->next;
 }
 return NULL;
}

//把節(jié)點(diǎn)放入OPEN 或CLOSED 表中
void Putinto(Node * suc,Lstack * list)
{
    Stack * temp;
 temp =(Stack *) malloc(sizeof(Stack));
 temp->npoint = suc;
 temp->next = (*list)->next;
 (*list)->next = temp;
}

///////////////計(jì)算f值部分-開(kāi)始//////////////////////////////
double Fvalue(Node suc, Node goal, float speed)
{//計(jì)算f值
 double Distance(Node,Node,int);
 double h = 0;
 for(int i = 1; i <= 8; i++)
  h = h + Distance(suc, goal, i);
 return h*speed + suc.g; //f = h + g(speed值增加時(shí)搜索過(guò)程以找到目標(biāo)為優(yōu)先因此可能不會(huì)返

回最優(yōu)解)                                      
}
double Distance(Node suc, Node goal, int i)
{//計(jì)算方格的錯(cuò)位距離
 int k,h1,h2;
 for(k = 0; k < 9; k++)
 {
  if(suc.data[k] == i)h1 = k;
  if(goal.data[k] == i)h2 = k;
 }
 return double(fabs(h1/3 - h2/3) + fabs(h1%3 - h2%3));
}
///////////////計(jì)算f值部分-結(jié)束//////////////////////////////

 

///////////////////////擴(kuò)展后繼節(jié)點(diǎn)部分的函數(shù)-開(kāi)始/////////////////
int BelongProgram(Lnode * suc ,Lstack * Open ,Lstack * Closed ,Node goal ,float speed)
{//判斷子節(jié)點(diǎn)是否屬于OPEN或CLOSED表 并作出相應(yīng)的處理
 Node * temp = NULL;
 int flag = 0;
 if((Belong(*suc,Open) != NULL) || (Belong(*suc,Closed) != NULL))
 {
  if(Belong(*suc,Open) != NULL) temp = Belong(*suc,Open);
  else temp = Belong(*suc,Closed);
  if(((*suc)->g) < (temp->g))
  {
   temp->parent = (*suc)->parent;
   temp->g = (*suc)->g;
   temp->f = (*suc)->f;
   flag = 1;
  }
 }
 else
 {
  Putinto(* suc, Open);
  (*suc)->f = Fvalue(**suc, goal, speed);
 }
 return flag;
}

void Spread(Lnode * suc, Lstack * Open, Lstack * Closed, Node goal, float speed)
{//擴(kuò)展后繼節(jié)點(diǎn)總函數(shù)
 int i;
 Node * child;
 for(i = 0; i < 4; i++)
 {
  if(Canspread(**suc, i+1))                   //判斷某個(gè)方向上的子節(jié)點(diǎn)可否擴(kuò)展
  {
   child = (Node *) malloc(sizeof(Node));  //擴(kuò)展子節(jié)點(diǎn)
   child->g = (*suc)->g +1;                //算子節(jié)點(diǎn)的g值
   child->parent = (*suc);                 //子節(jié)點(diǎn)父指針指向父節(jié)點(diǎn)
   Spreadchild(child, i);                  //向該方向移動(dòng)空格生成子節(jié)點(diǎn)
   if(BelongProgram(&child, Open, Closed, goal, speed)) // 判斷子節(jié)點(diǎn)是否屬

于OPEN或CLOSED表 并作出相應(yīng)的處理
    free(child);
  }
 }
}
///////////////////////擴(kuò)展后繼節(jié)點(diǎn)部分的函數(shù)-結(jié)束//////////////////////////////////

Node * Process(Lnode * org, Lnode * goal, Lstack * Open, Lstack * Closed, float speed)
{//總執(zhí)行函數(shù)
 while(1)
 {
  if((*Open)->next == NULL)return NULL;  //判斷OPEN表是否為空,為空則失敗退出
  Node * minf = Minf(Open);              //從OPEN表中取出f值最小的節(jié)點(diǎn)
  Putinto(minf, Closed);                 //將節(jié)點(diǎn)放入CLOSED表中
  if(Equal(minf, *goal))return minf;     //如果當(dāng)前節(jié)點(diǎn)是目標(biāo)節(jié)點(diǎn),則成功退出
        Spread(&minf, Open, Closed, **goal, speed);   //當(dāng)前節(jié)點(diǎn)不是目標(biāo)節(jié)點(diǎn)時(shí)擴(kuò)展當(dāng)前節(jié)點(diǎn)的后繼

節(jié)點(diǎn)
 }
}

int Shownum(Node * result)
{//遞歸顯示從初始狀態(tài)到達(dá)目標(biāo)狀態(tài)的移動(dòng)方法
 if(result == NULL)return 0;
 else
 {
  int n = Shownum(result->parent);
  for(int i = 0; i < 3; i++)
  {
   printf("/n");
   for(int j = 0; j < 3; j++)
   {
    if(result->data[i*3+j] != 0)
     printf(" %d ",result->data[i*3+j]);
    else printf("   ");
   }
  }
  printf("/n");
  return n+1;
 }
}

完。July、二零一一年三月十日。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多