雙向廣度優先搜尋演算法是對廣度優先演算法的一種擴充套件。廣度優先演算法從起始節點以廣度優先的順序不斷擴充套件,
直到遇到目的節點;而雙向廣度優先演算法從兩個方向以廣度優先的順序同時擴充套件,乙個是從起始節點開始擴充套件,另
乙個是從目的節點擴充套件,直到乙個擴充套件佇列中出現另外乙個佇列中已經擴充套件的節點,也就相當於兩個擴充套件方向出現了
交點,那麼可以認為我們找到了一條路徑。雙向廣度優先演算法相對於廣度優先演算法來說,由於採用了從兩個跟開始擴充套件
的方式,搜尋樹的深度得到了明顯的減少,所以在演算法的時間複雜度和空間複雜度上都有較大的優勢!雙向廣度優先算
法特別適合於給出了起始節點和目的節點,要求他們之間的最短路徑的問題。另外需要說明的是,廣度優先的順序能夠保證
找到的路徑就是最短路徑!
基於以上思想,我們給出雙向廣度優先演算法程式設計的基本框架如下:
資料結構:
queue q1, q2; //兩個佇列分別用於兩個方向的擴充套件(注意在一般的廣度優先演算法中,只需要乙個佇列)
int head[2], tail[2]; //兩個佇列的頭指標和尾指標
演算法流程:
一、主控函式:
void solve()
二、擴充套件函式:
int expand(i) //其中i為佇列的編號(表示q0或者q1)
三、判斷新節點是否在同乙個佇列中重複的函式
int isduplicate(i, j) //i為佇列編號,j為當前節點在佇列中的指標
四、判斷當前擴充套件出的節點是否在另外乙個佇列出現,也就是判斷相交的函式:
int isintersect(i,j) //i為佇列編號,j為當前節點在佇列中的指標
以上為雙向廣度優先搜尋演算法的基本思路,下面給出使用上面的演算法框架編寫的八數碼問題的**:
問題描述:
給定 3 x 3 的矩陣如下:
2 3 4
1 5 x
7 6 8
程式每次可以交換"x"和它上下左右的數字,
經過多次移動後得到如下狀態:
1 2 3
4 5 6
7 8 x
輸出在最少移動步數的情況下的移動路徑[每次移動的方向上下左右依次表示為'u', 'd', 'l', 'r']
例如:如果過輸入:【將矩陣放到一行輸出】
2 3 4 1 5 x 7 6 8
則輸出:
ullddrurdllurdruldr
原題見acm pku 1077
/** author: puresky
* date: 2010.01.12
* purpose: solve eigth number problem!*/
#include
#include
#include
#define maxn 1000000
#define swap(a, b)
typedef struct _node node;
struct _node;
int head[2], tail[2];
node queue[2][maxn];// two queues for double directoin bfs
//shift of moving up, down, left ,right
int shift[4][2] = , , , };
//for output direction!
char dir[4][2] = , , , };
//test case
char start[10] = "23415x768";
char end[10] = "12345678x";
//read a tile 3 by 3
void readtile()
start[9] = '\0';}
//print result
void print_backward(int i)
}void print_forward(int j)
}void print_result(int i, int j)
//init the queue
void init(int qi, const char* state)
//check if there are duplicates in the queue
//time comlexity:o(n)
//we can optimise this function using hashtable
int isduplicate(int qi)
}return 0;}
//check if the current node is in another queue!
//time comlexity:o(n)
//we can optimise this function using hashtable
int isintersect(int qi)}
return -1;}
//expand nodes
int expand(int qi)
else
else
return 1;}}
}}return 0;}
//call expand to generate queues
int solve()
else
}while(head[0] <= tail[0]) if(expand(0)) return 1;
while(head[1] <= tail[1]) if(expand(1)) return 1;
return 0;}
int main(int argc, char** argv)
//system("pause"); //pause
return 0;}
acm judge online: 372k 記憶體, 938ms 時間
使用hashtable優化後的版本見:《八數碼問題hashtable優化查詢後的版本》
雙向廣度優先搜尋演算法
首先是廣度優先搜尋演算法 初始化visited陣列,將所有點的值設為false visited陣列用來儲存所有點的訪問情況 visited start true start為起始點 queuesearch 用來儲存待搜尋點的佇列 search.push start while search.empt...
廣度優先搜尋演算法
廣度優先搜尋 bfs 這個是第乙個研究的課題,廣度優先搜尋也叫寬度優先搜尋,英文為breadth first searth,開始看的時候一頭霧水,基本也能懂大致意思,但是還不是真正的理解,今天又仔細看看,大致理解上又更深了一層吧。下面來總結下,自己的一些體會,以及對它的獨到的理解。大的方面來說它是一...
廣度優先搜尋演算法
在深度優先搜尋中,深度越大的結點越先得到擴充套件。如果把它改為深度越小的結點越先得到擴充套件,就是廣度優先搜尋法。廣度優先搜尋演算法的基本思想 1 建立乙個空的狀態佇列ss 2 建立乙個空的狀態庫sb 3 把初始狀態s 0 存入佇列ss中 4 若佇列狀態是目標狀態,則搜尋成功,演算法執行中止。如該狀...