DFS(深度優先搜尋樹) 遞迴非遞迴實現
阿新 • • 發佈:2019-02-10
一、鄰接矩陣
1、遞迴
有限制條件,如果不是連通圖,那麼找不完,必須要用for遍歷每個頂點
思想:從指定的v頂點出發,訪問他,標記為已經訪問。然後,尋找跟這個v頂點連線的每一條邊(for迴圈),如果滿足有邊+未被訪問,則遞迴呼叫
//矩陣的深度遞迴搜尋
void DFS_matric(MGraph Graph,Vertex v,void(*visit_)(Vertex)){
int i;
visit_(v);
visited[v]=true;
for(i=0;i<Graph->nv;i++){
//跟這個頂點有邊並且還沒有被訪問
if(Graph->G[v][i]<INFINITY && visited[i]==false)
DFS_matric(Graph,i,visit_);//一直遞迴呼叫
}
}
2、非遞迴
//後邊才補上來,現在寫的有些問題
這裡寫程式碼片
二、鄰接表
1、遞迴
從給定的v頂點去訪問,如何找跟他連線的頂點?這個時候先找到他的那一行邊表,再找到頭指標指向的位置,w的型別使指標PtrToAdjvNode型別。如果第一個被訪問了,就再找w的下一個,最多可以一直找到尾巴,就是w變成NULL。(可以結合前面的鄰接表的建立文章來看)
w=Graph->G[v].firstEdge;
//鄰接表的深度搜索遞迴
void DFS_adjacencyList(LGraph Graph,Vertex v,void(*visit_)(Vertex)){
PtrToAdjvNode w;
visit_(v);
visited[v]=true;
for(w=Graph->G[v].firstEdge;w;w=w->next){
if(!visited[w->Adjv])//下一個頂點沒有被訪問
DFS_adjacencyList(Graph,w->Adjv,visit_);
}
}
2、非遞迴
這裡演示一個不是連通圖的該怎麼遍歷。
非遞迴需要使用佇列。規則:凡是訪問過的,都加進佇列,深度走不下去了,就刪除一個元素出來用。
A、對每一個頂點用for遍歷。判斷是否訪問,如果沒有訪問,則訪問他,並且標記,再加進佇列裡。
B、再判斷佇列是否為空,如果不空,(開始深度迴圈地尋找)就開始按著剛才訪問的元素切入。找到這個元素的邊表的指向的元素,一個一個找,如果標記過就下一個,沒有標記過,就訪問這個元素,加入佇列。再把尋找重心放到這個找到的元素,找他的邊表,一直重複。
C、直到某個邊表到尾了,跳出深度搜索的while。這時,刪除一個元素,把重心放到這個元素,尋找他的邊錶行,
D、一直到所有元素都訪問了。
//鄰接表的深度搜索非遞迴
void In_DFS_adjacencyList(LGraph Graph,Vertex v,void(*visit_)(Vertex)){
PtrToAdjvNode p;
queue Q;
Q=CreatQueue();
int i;
for(i=0;i<Graph->nv;i++){
if(!visited[i]){//如果未訪問,則訪問
visit_(i);
visited[i]=true;
addQ(Q,i);
p=Graph->G[i].firstEdge;
while(!isEmpty(Q)){
while(p){
//如果沒有被訪問
if(!visited[p->Adjv]){
visited[p->Adjv]=true;
visit_(p->Adjv);
addQ(Q,p->Adjv);
//如果能找到這個結點,就走這條路,掉頭
p=Graph->G[p->Adjv].firstEdge;
}else{
p=p->next;
}
}
v=deleteQ(Q);
p=Graph->G[v].firstEdge;
}
}
}
}