日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法之图搜索算法(一)

發(fā)布時(shí)間:2025/3/21 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法之图搜索算法(一) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
1. 介紹

本文介紹了比較初級(jí)的圖搜索算法,包括深度優(yōu)先遍歷,廣度優(yōu)先遍歷和雙向廣度優(yōu)先遍歷。

2. 深度優(yōu)先遍歷DFS

2.1 算法思想

從圖中某個(gè)頂點(diǎn)v開始,訪問此節(jié)點(diǎn),然后依次從v中未被訪問的鄰接點(diǎn)出發(fā)深度優(yōu)先遍歷圖,直到圖中上所有和v有路徑相通的頂點(diǎn)都被訪問;若此時(shí)圖中尚有頂點(diǎn)未被訪問,則另選圖中一個(gè)未被訪問頂點(diǎn)做起點(diǎn),重復(fù)以上過程,直到圖中所有頂點(diǎn)都被訪問為止。

深度優(yōu)先搜索遍歷類似于樹的先序遍歷。假定給定圖G的初態(tài)是所有頂點(diǎn)均未被訪問過,在G中任選一個(gè)頂點(diǎn)i作為遍歷的初始點(diǎn),則深度優(yōu)先搜索遍歷可定義如下:

(1) 首先訪問頂點(diǎn)i,并將其訪問標(biāo)記置為訪問過,即visited[i]=1;

(2) 然后搜索與頂點(diǎn)i有邊相連的下一個(gè)頂點(diǎn)j,若j未被訪問過,則訪問它,并將j的訪問標(biāo)記置為訪問過,visited[j]=1,然后從j開始重復(fù)此過程,若j已訪問,再看與i有邊相連的其它頂點(diǎn);

(3) 若與i有邊相連的頂點(diǎn)都被訪問過,則退回到前一個(gè)訪問頂點(diǎn)并重復(fù)剛才過程,直到圖中所有頂點(diǎn)都被訪問完止。

2.2 算法實(shí)現(xiàn)

鄰接矩陣的算法描述為下面形式:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void dfs1 (graph & g, int i, int n)???????? // 從頂點(diǎn)i 出發(fā)遍歷 { ??cout<<g.v[i];??????????????? //輸出訪問頂點(diǎn) ??visited[i]=1;??????????????????? //訪問標(biāo)記置1表示已經(jīng)訪問 ??for(j=1; j<=n; j++) ????if ((g.arcs[i ][j]= =1)&&(!visited[j])) ??????dfs(g,j,n); }

鄰接表算法描述為下面形式:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 void? dfs2(adjlist GL,int i, int n) { ??cout<<i<<‘’ ;????????????? //輸出訪問頂點(diǎn) ??visted[i]=1;??????????? //訪問標(biāo)記置為1表示已訪問 ??edgenode * p=GL[i]; ??while (p!=NULL) ??{ ?????if? (!visited[p->adjvex]) ???????dfs2(p->adjvex); ?????p=p->next; ??} ?}

2.3 適用范圍

需要有順序遍歷圖,且找到一個(gè)解后輸出即可。如:trie樹排序

多用于只要求解,并且解答樹中的重復(fù)節(jié)點(diǎn)較多并且重復(fù)較難判斷時(shí)使用,但往往可以用A*或回溯算法代替。

2.4 舉例

數(shù)獨(dú)求解。給出一個(gè)不完整的數(shù)獨(dú),讓填充其中空白的數(shù)字。

更多題目:

POJ 1321 棋盤問題:http://www.cublog.cn/u3/105033/showart_2212140.html

類迷宮問題:http://www.jguoer.com/post/2010/02/17/DFS-Code.aspx

數(shù)獨(dú)問題:http://acm.hdu.edu.cn/showproblem.php?pid=1426

3. 廣度優(yōu)先遍歷BFS

3.1 算法思想

廣度優(yōu)先搜索遍歷類似于樹的按層次遍歷。設(shè)圖G的初態(tài)是所有頂點(diǎn)均未訪問,在G 任選一頂點(diǎn)i作為初始點(diǎn),則廣度優(yōu)先搜索的基本思想是:

(1)首先訪問頂點(diǎn)i,并將其訪問標(biāo)志置為已被訪問,即visited[i]=1;

(2)接著依次訪問與頂點(diǎn)i有邊相連的所有頂點(diǎn)W1,W2,…,Wt;

(3)然后再按順序訪問與W1,W2,…,Wt有邊相連又未曾訪問過的頂點(diǎn);

依此類推,直到圖中所有頂點(diǎn)都被訪問完為止。

3.2 算法實(shí)現(xiàn)

用鄰接矩陣的算法描述如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 void? bfs1( graph g, int? i)?????? //從頂點(diǎn)i出發(fā)遍歷 { ??Queue? Q ;???????? //Q為隊(duì)列 ??InitQueue(Q) ??cout<<g.v[i] ;??????? // 輸出訪問頂點(diǎn) ??visited[i]=1 ;???????? //標(biāo)記置1表示已經(jīng)訪問 ??Qinsert(Q,i) ;????????? //入隊(duì)列 ??while (!Queueempty(Q)) ??{ ????int k=Qdelete(Q); ????for (j=0; j<n; j++) ????{ ??????if ((g.a[i][j]==1)&&(!visited[j])) ??????{ ????????cout<<g.v[j]; ????????visited[j]=1 ; ????????Qinsert(Q,i) ; ??????} ????} ??} }

用鄰接矩陣的算法描述如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 void? bfs2(adjlist GL, int i, int n) { ??Queue Q ; ??InitQueue(Q);?????????????? //定義隊(duì)列 ??cout<<i<<‘’; ??visited[i]=1; ??Qinsert(Q,i)??????????????????????????????? //進(jìn)隊(duì) ??while (!QueueEmpty(Q)) ??{ ????int k=Qdelete(Q) ;??????????? //出隊(duì) ????edgenode* p=GL[k]; ????while? (p!=NULL) ????{ ??????if (!visited[p->adjvex]) ??????{ ????????cout<<j; ????????visited[p->data]=1; ????????Qinsert(Q); ??????} ????p=p->next; ????} ??} }

3.3 適用范圍

求問題的最優(yōu)解

3.4 舉例

給定一個(gè)8*8的格子地圖,再給定初始狀態(tài)和終止?fàn)顟B(tài),輸出從初始點(diǎn)到達(dá)終止點(diǎn)的最少步數(shù)。

更多題目:

http://www.cppblog.com/firstnode/archive/2009/03/07/75839.html

http://blog.sina.com.cn/s/blog_6635898a0100hwe3.html

http://blog.csdn.net/super_chris/archive/2009/12/26/5082666.aspx

http://www.chenyajun.com/2010/05/08/4540

4. 雙向廣度優(yōu)先遍歷

4.1 算法思想

有些問題按照廣度優(yōu)先搜索法則擴(kuò)展結(jié)點(diǎn)的規(guī)則,既適合順序,也適合逆序,于是我們考慮在尋找目標(biāo)結(jié)點(diǎn)或路徑的搜索過程中,初始結(jié)點(diǎn)向目標(biāo)結(jié)點(diǎn)和目標(biāo)結(jié)點(diǎn)向初始結(jié)點(diǎn)同時(shí)進(jìn)行擴(kuò)展,直至在兩個(gè)擴(kuò)展方向上出現(xiàn)同一個(gè)子結(jié)點(diǎn),搜索結(jié)束,這就是雙向搜索過程。

出現(xiàn)的這個(gè)同一子結(jié)點(diǎn),我們稱為相交點(diǎn),如果確實(shí)存在一條從初始結(jié)點(diǎn)到目標(biāo)結(jié)點(diǎn)的最佳路徑,那么按雙向搜索進(jìn)行搜索必然會(huì)在某層出現(xiàn)“相交”,即有相交點(diǎn),初始結(jié)點(diǎn)一相交點(diǎn)一目標(biāo)結(jié)點(diǎn)所形成的一條路徑即是所求路徑。

4.2 算法實(shí)現(xiàn)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 now = 0; Q.push(st);??? RQ.push(ed); mark[st] = true;??? Rmark[ed] = true; while(!Q.empty() && !RQ.empty()) { // 兩邊的擴(kuò)展方式須為按層擴(kuò)展 ??while(Q.front().step == now) ??{ //step表示節(jié)點(diǎn)的層數(shù) ????nextState = extend(Q.front); t ????if(mark[nextState]) continuel ????if(Rmark[nextState]) return true; ??} ??while(RQ.front().step == now) ??{ ????nextState = extend(RQ.front); ????if(Rmark[nextState]) continuel ????if(mark[nextState]) return true; ??} ??now++; }

4.3 適用范圍

最優(yōu)化問題中,知道問題的起始狀態(tài)和最終狀態(tài),且兩個(gè)狀態(tài)可相互到達(dá)。

4.4 舉例

棋盤上有四個(gè)棋子,給你兩個(gè)狀態(tài),問可否8步內(nèi)將一個(gè)狀態(tài)轉(zhuǎn)移到另一個(gè)狀態(tài)?

5. DFS與BFS比較

數(shù)據(jù)結(jié)構(gòu):DFS采用棧,而BFS采用隊(duì)列

算法思想:深度搜索與廣度搜索的控制結(jié)構(gòu)和產(chǎn)生系統(tǒng)很相似,唯一的區(qū)別在于對(duì)擴(kuò)展節(jié)點(diǎn)選取上。由于其保留了所有的前繼節(jié)點(diǎn),所以在產(chǎn)生后繼節(jié)點(diǎn)時(shí)可以去掉一部分重復(fù)的節(jié)點(diǎn),從而提高了搜索效率。這兩種算法每次都擴(kuò)展一個(gè)節(jié)點(diǎn)的所有子節(jié)點(diǎn),而不同的是,深度搜索下一次擴(kuò)展的是本次擴(kuò)展出來的子節(jié)點(diǎn)中的一個(gè),而廣度搜索擴(kuò)展的則是本次擴(kuò)展的節(jié)點(diǎn)的兄弟節(jié)點(diǎn)

使用范圍:DFS可以迅速的找到一個(gè)解,然后利用這個(gè)解進(jìn)行剪枝,而BFS可找到最優(yōu)解。

原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明:?轉(zhuǎn)載自董的博客

本文鏈接地址:?http://dongxicheng.org/structure/basic-graph-search/

總結(jié)

以上是生活随笔為你收集整理的算法之图搜索算法(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。