深度優先搜尋和廣度優先搜尋理解及經典例題(java)
阿新 • • 發佈:2019-01-03
簡介
深度優先搜尋和廣度優先搜尋應用得最多的是對圖的搜尋。深度優先即是沿著一條路一直走到底,然後進行回溯。而廣度優先則是優先搜尋所有相鄰的節點,再訪問所有相鄰節點的鄰節點。
圖的遍歷之 深度優先搜尋和廣度優先搜尋這篇文章中的兩幅圖做了非常清楚的描述:
適用範圍
廣度優先搜尋,適用於所有情況下的搜尋,但是深度優先搜尋不一定能適用於所有情況下的搜尋。因為由於一個有解的問題樹可能含有無窮分枝,深度優先搜尋如果誤入無窮分枝(即深度無限),則不可能找到目標節點。所以,深度優先搜尋策略是不完備的。
所以在未知樹深度情況下,用這種演算法很保險和安全。在樹體系相對小不龐大的時候,廣度優先也會更好些。但是在樹深度已知情況下,並且樹體系相當龐大時,深度優先搜尋往往會比廣度優先搜尋優秀,因為比如8*8的馬踏棋盤中,如果用廣度搜索,必須要記錄所有節點的資訊,這個儲存量一般電腦是達不到的。然而如果用深度優先搜尋的時候卻能在一個棋盤被判定出來後釋放之前的節點記憶體。
經典例題
1.八皇后問題
在8*8的國際象棋棋盤上,要求在每一行(或者每一列)放置一個皇后,且能做到在水平方向、豎直方向和斜方向都沒有衝突。請列出所有解法。
最終的解肯定每行都有一個皇后,那麼我們直接採用深度優先搜尋遍歷所有可能即可,在過程中將解儲存起來。
程式碼:
package dataStructureAndAlgorithms;
import java.util.ArrayList;
import java.util.List;
public class EightQueenProblem {
static List<int[]> result = new ArrayList<int[]>();
static int n = 8;
/**
*
* @param row 範圍 0~7
* @param used 第n行皇后的位置
* @param result
*/
public static void calQueenPosition(int rowNow, int[] used){
//搜尋結束條件
if(rowNow == n){
int[] temp = new int[n];
System.arraycopy(used, 0 , temp, 0, n);
result.add(temp);
return;
}
//查詢合適的列
for(int col=0;col<n;col++){
if(isColOk(used,rowNow,col)){
used[rowNow] = col;
calQueenPosition(rowNow+1, used);
}
}
}
public static boolean isColOk(int[] used,int rowNow, int col){
for(int i=0;i<rowNow;i++){
//在同一行
if(used[i] == col ){
return false;
}
//斜線方向上:y=x+b;
if(i-used[i] == rowNow - col ){
return false;
}
//另一個斜線方程上:y=-x+b;
if(i+used[i] == rowNow + col ){
return false;
}
}
return true;
}
public static void main(String[] args) {
int[] used = new int[n];
calQueenPosition(0, used);
int total = result.size();
System.out.println(total);
//列印結果
for(int i=0;i<total;i++){
System.out.println("********");
used = result.get(i);
for(int j=0;j<n;j++){
for(int k=0;k<used[j];k++){
System.out.print(k+1 + " ");
}
System.out.print("# ");
for(int k=used[j]+1;k<n;k++){
System.out.print(k+1 + " ");
}
System.out.println();
}
System.out.println();
}
}
}