在我們遇到的一些問題當中,有些問題我們不能夠確切的找出數學模型,即找不出一種直接求解的方法,解決這一類問題,我們一般採用搜尋的方法解決。搜尋就是用問題的所有可能去試探,按照一定的順序、規則,不斷去試探,直到找到問題的解,試完了也沒有找到解,那就是無解,試探時一定要試探完所有的情況(實際上就是窮舉)。
深度優先搜尋
深度優先搜尋,過程簡要來說是對每乙個可能的分支路徑深入到不能再深入為止,而且每個節點只能訪問一次。關鍵在於解決「當下該如何做」。至於下一步如何做應該是和當下如何做是一樣的。因此函式的功能就是解決當下你該怎麼辦,通常的方法就是把每一種可能都嘗試一遍(可以使用for迴圈來遍歷)。當解決完這一步後便進入下一步,下一步的解決方案應該是和這一步是一樣的,所以會使用遞迴來做接下來的處理。
深度優先搜尋的基本模型
void
function
(int step)返回}
每一種嘗試就是一種「擴充套件」,每一種擴充套件就是一種方式,在此就可以判斷各種方式是否可以擴充套件成功。
廣度優先搜尋
廣度優先搜尋,也稱為寬度優先搜尋,它的特點就是層層遞進。廣度優先搜尋一般使用佇列來實現,相對於深度優先搜尋的遞迴方式來說,廣度優先搜尋更像是將所有的情況按層級放入佇列然後依次鋪展開來。
深度和廣度優先搜尋的深度和廣度是針對圖的遍歷。遍歷就是把圖的每乙個頂點都訪問一次。
深度優先遍歷的主要思想是先以乙個未被訪問過得頂點作為起始頂點,沿當前頂點的邊走到未被訪問過得頂點;當沒有未訪問過得頂點時,則回到上乙個頂點,繼續試探訪問別的頂點,直到所有的頂點都被訪問過。所以,深度優先遍歷是先沿著一條分支遍歷直到末端,然後回溯,再沿著另一條進行同樣的遍歷,直到所有的頂點都被訪問過為止。
廣度優先遍歷,首先以乙個未被訪問過的頂點作為起始頂點,訪問其所有相鄰的頂點,然後對每個相鄰的頂點,再訪問它們相鄰的未被訪問過得頂點,直到所有的頂點都被訪問過,遍歷結束。
如下圖:
上圖中深度優先遍歷圖示如下,頂點邊的數字為訪問順序。
上圖中廣度優先遍歷圖示如下,頂點邊的數字為訪問順序。
接下來舉個迷宮例子,分別用深度優先和廣度優先搜尋實現。
案例描述:將迷宮抽象為二維平面圖,分別設定障礙物和空地, 給出起始點和終點,計算出其中最短的路徑需要的步數。
具體模型:給出迷宮地圖座標,用二維陣列即可表示。分別可以上下左右四個方向行走,陣列值表示障礙物和空地,分別用1和0表示。
深度優先搜尋:
示例**如下:
#include
#include
int n,m,p,q,min=99999999;
int a[51][51],book[51][51];
void dfs(int x,int y, int step);
int main(void)
void dfs(int x, int y, int step)
,,,};//分別向右下左上方向走
int tx,ty,k;
//判斷是否到達指定位置
if(x==p&&y==q)
for(k=0;k<=3;k++)
}return;
}
結果如下圖
最後梳理一下例子中深度優先搜尋的過程,首先必須先判斷是否已經到達終點,這是遞迴返回的關鍵;然後搜尋下乙個點,計算座標,判斷此座標是否在地圖中,其次排除掉已經在這條路徑中走過和障礙物無法到達的,那這個座標就是可以加入路徑的,進行標記然後進入遞迴的下乙個座標重複上述步驟。
其中有乙個關鍵的地方在於,遞迴返回時,需要將本次標記的點請出標記,以至下一條路徑可以再次訪問這個點,從而找出其中最短的路徑。
廣度優先搜尋:
示例**如下:
struct note
;struct print
;int a[51][51],book[51][51];
int m,n,startx,starty,p,q;
void read();
int main(void)
,,,};//分別向右下左上方向走
int w,printftail,k,tx,ty,flag;
//讀入地圖及其他相關引數
read();
//佇列初始化;
head=1;
tail=1;
//迷宮入口座標入隊
que[tail].x=startx;
que[tail].y=starty;
que[tail].father=0;
que[tail].step=0;
tail++;
book[startx][starty]=1;
flag=0;//標記是否到達終點
while(headfor(k=0;k<=3;k++)
//若走到了終點,則停止擴充套件,退出迴圈
if(tx==p&&ty==q)
}if(1==flag)
break;
head++;//乙個點的四個方向都嘗試完後才能進入下乙個點
}//此時,佇列中最後乙個點的步數就是要求的步數
printf("the shortest step from start to end: %d\n",que[tail-1].step);
printf("the shortest path from start to end: \n");
//列印最短的路徑
printftail=tail-1;
w=1;
while(que[printftail].father!=0)
w--;//隊尾指向最後乙個元素的下一位
while(w>0)
printf("\n");
return0;}
//讀入迷宮和相關入口出口引數函式
void read()
結果如下圖:
廣度優先搜尋,利用將乙個點的所有可能的路徑選擇都放入佇列中再對下一層進行擴充套件。記憶體耗費上比深度優先搜尋大,不過理解簡單實現方便。例子中廣度優先搜尋解決方案中增加了對最短路徑的記錄,同樣深度優先也可以標記路徑,只是會比廣度優先麻煩一些,這裡就沒有再展開討論。
volatile的兩大性質
一 可見性 public class public void load catch interruptedexception e 3 println,也可以跳出while迴圈 能 synchronized 可見性保證 記憶體屏障 4 shortwait 休眠納秒 休眠1秒 能 shortwait 1...
GRE考試寫作的兩大技巧
gre寫作技巧運用好gre寫作范文,它是最好的備考素材,gre閱讀部分的文章也是我們有針對性地閱讀的乙個素材庫,要扎扎實實地提高英語gre考試寫作水平,就必須要以扎扎實實的閱讀量為前提之一,必須體會地道的 漂亮的語言是怎麼寫出來的,通過對范文的語言內容和邏輯的理解來學習gre考試寫作中詞彙的使用 句...
django中queryset的兩大特性
roles roleinfo.objects.all 建立查詢集的時候,是不會訪問資料庫的,直到真正的呼叫資料的時候,才會訪問資料庫,所以 roles roleinfo.objects.all 沒有真正的進行資料庫查詢的,只是建立了乙個資料庫查詢集 呼叫資料,真正的使用資料 1 迭代 2 序列化 3...