
經(jīng)典算法研究系列;BFS和DFS優(yōu)先搜索算法(2)
圖的深度優(yōu)先遍歷演示系統(tǒng):
http://sjjg.js.zwu.edu.cn/SFXX/sf1/sdyxbl.html
===============
最后,咱們再來看深度優(yōu)先搜索的遞歸實現(xiàn)與非遞歸實現(xiàn)
1、DFS 遞歸實現(xiàn):
void dftR(PGraphMatrix inGraph)
{
PVexType v;
assertF(inGraph!=NULL,"in dftR, pass in inGraph is null/n");
printf("/n===start of dft recursive version===/n");
for(v=firstVertex(inGraph);v!=NULL;v=nextVertex(inGraph,v))
if(v->marked==0)
dfsR(inGraph,v);
printf("/n===end of dft recursive version===/n");
}
void dfsR(PGraphMatrix inGraph,PVexType inV)
{
PVexType v1;
assertF(inGraph!=NULL,"in dfsR,inGraph is null/n");
assertF(inV!=NULL,"in dfsR,inV is null/n");
inV->marked=1;
visit(inV);
for(v1=firstAdjacent(inGraph,inV);v1!=NULL;v1=nextAdjacent(inGraph,inV,v1))
//v1當為v的鄰接點。
if(v1->marked==0)
dfsR(inGraph,v1);
}
2、DFS 非遞歸實現(xiàn)
非遞歸版本---借助結(jié)點類型為隊列的棧實現(xiàn)
聯(lián)系樹的前序遍歷的非遞歸實現(xiàn):
可知,其中無非是分成“探左”和“訪右”兩大塊訪右需借助棧中彈出的結(jié)點進行.
在圖的深度優(yōu)先搜索中,同樣可分成“深度探索”和“回訪上層未訪結(jié)點”兩塊:
1、圖的深度探索這樣一個過程和樹的“探左”完全一致,
只要對已訪問過的結(jié)點作一個判定即可。
2、而圖的回訪上層未訪結(jié)點和樹的前序遍歷中的“訪右”也是一致的.
但是,對于樹而言,是提供rightSibling這樣的操作的,因而訪右相當好實現(xiàn)。
在這里,若要實現(xiàn)相應的功能,考慮將每一個當前結(jié)點的下層結(jié)點中,如果有m個未訪問結(jié)點,
則最左的一個需要訪問,而將剩余的m-1個結(jié)點按從左到右的順序推入一個隊列中。
并將這個隊列壓入一個堆棧中。
這樣,當當前的結(jié)點的鄰接點均已訪問或無鄰接點需要回訪時,
則從棧頂?shù)年犃薪Y(jié)點中彈出隊列元素,將隊列中的結(jié)點元素依次出隊,
若已訪問,則繼續(xù)出隊(當當前隊列結(jié)點已空時,則繼續(xù)出棧,彈出下一個棧頂?shù)年犃?,
直至遇到有未訪問結(jié)點(訪問并置當前點為該點)或直到棧為空(則當前的深度優(yōu)先搜索樹停止搜索)。
將算法通過精簡過的C源程序的方式描述如下:
//dfsUR:功能從一個樹的某個結(jié)點inV發(fā),以深度優(yōu)先的原則訪問所有與它相鄰的結(jié)點
void dfsUR(PGraphMatrix inGraph,PVexType inV)
{
PSingleRearSeqQueue tmpQ; //定義臨時隊列,用以接受棧頂隊列及壓棧時使用
PSeqStack testStack; //存放當前層中的m-1個未訪問結(jié)點構(gòu)成隊列的堆棧.
//一些變量聲明,初始化動作
//訪問當前結(jié)點
inV->marked=1; //當marked值為1時將不必再訪問。
visit(inV);
do
{
flag2=0;
//flag2是一個重要的標志變量,用以、說明當前結(jié)點的所有未訪問結(jié)點的個數(shù),兩個以上的用2代表
//flag2:0:current node has no adjacent which has not been visited.
//1:current node has only one adjacent node which has not been visited.
//2:current node has more than one adjacent node which have not been visited.
v1=firstAdjacent(inGraph,inV); //鄰接點v1
while(v1!=NULL) //訪問當前結(jié)點的所有鄰接點
{
if(v1->marked==0) //..
{
if(flag2==0) //當前結(jié)點的鄰接點有0個未訪問
{
//首先,訪問最左結(jié)點
visit(v1);
v1->marked=1; //訪問完成
flag2=1; //
//記錄最左兒子
lChildV=v1;
//save the current node's first unvisited(has been visited at this time)adjacent node
}
else if(flag2==1) //當前結(jié)點的鄰接點有1個未訪問
{
//新建一個隊列,申請空間,并加入第一個結(jié)點
flag2=2;
}
else if(flag2==2)//當前結(jié)點的鄰接點有2個未被訪問
{
enQueue(tmpQ,v1);
}
}
v1=nextAdjacent(inGraph,inV,v1);
}
if(flag2==2)//push adjacent nodes which are not visited.
{
//將存有當前結(jié)點的m-1個未訪問鄰接點的隊列壓棧
seqPush(testStack,tmpQ);
inV=lChildV;
}
else if(flag2==1)//only has one adjacent which has been visited.
{
//只有一個最左兒子,則置當前點為最左兒子
inV=lChildV;
}
else if(flag2==0)
//has no adjacent nodes or all adjacent nodes has been visited
{
//當當前的結(jié)點的鄰接點均已訪問或無鄰接點需要回訪時,則從棧頂?shù)年犃薪Y(jié)點中彈出隊列元素,
//將隊列中的結(jié)點元素依次出隊,若已訪問,則繼續(xù)出隊(當當前隊列結(jié)點已空時,
//則繼續(xù)出棧,彈出下一個棧頂?shù)年犃?,直至遇到有未訪問結(jié)點(訪問并置當前點為該點)或直到棧為空。
flag=0;
while(!isNullSeqStack(testStack)&&!flag)
{
v1=frontQueueInSt(testStack); //返回棧頂結(jié)點的隊列中的隊首元素
deQueueInSt(testStack); //將棧頂結(jié)點的隊列中的隊首元素彈出
if(v1->marked==0)
{
visit(v1);
v1->marked=1;
inV=v1;
flag=1;
}
}
}
}while(!isNullSeqStack(testStack));//the algorithm ends when the stack is null
}
數(shù)據(jù)分析咨詢請掃描二維碼
若不方便掃碼,搜微信號:CDAshujufenxi
2025被稱為“AI元年”,而AI,與數(shù)據(jù)密不可分。網(wǎng)易公司創(chuàng)始人丁磊在《AI思維:從數(shù)據(jù)中創(chuàng)造價值的煉金術》一書中指出:AI思維, ...
2025-07-17數(shù)據(jù)分析師的技能圖譜:從數(shù)據(jù)到價值的橋梁? 在數(shù)據(jù)驅(qū)動決策的時代,數(shù)據(jù)分析師如同 “數(shù)據(jù)翻譯官”,將冰冷的數(shù)字轉(zhuǎn)化為清晰的 ...
2025-07-17Pandas 寫入指定行數(shù)據(jù):數(shù)據(jù)精細化管理的核心技能? 在數(shù)據(jù)處理的日常工作中,我們常常需要面對這樣的場景:在龐大的數(shù)據(jù)集里精 ...
2025-07-17解碼 CDA:數(shù)據(jù)時代的通行證? 在數(shù)字化浪潮席卷全球的今天,當企業(yè)決策者盯著屏幕上跳動的數(shù)據(jù)曲線尋找增長密碼,當科研人員在 ...
2025-07-17CDA 精益業(yè)務數(shù)據(jù)分析:數(shù)據(jù)驅(qū)動業(yè)務增長的實戰(zhàn)方法論 在企業(yè)數(shù)字化轉(zhuǎn)型的浪潮中,“數(shù)據(jù)分析” 已從 “加分項” 成為 “必修課 ...
2025-07-16MySQL 中 ADD KEY 與 ADD INDEX 詳解:用法、差異與優(yōu)化實踐 在 MySQL 數(shù)據(jù)庫表結(jié)構(gòu)設計中,索引是提升查詢性能的核心手段。無論 ...
2025-07-16解析 MySQL Update 語句中 “query end” 狀態(tài):含義、成因與優(yōu)化指南? 在 MySQL 數(shù)據(jù)庫的日常運維與開發(fā)中,開發(fā)者和 DBA 常會 ...
2025-07-16如何考取數(shù)據(jù)分析師證書:以 CDA 為例? ? 在數(shù)字化浪潮席卷各行各業(yè)的當下,數(shù)據(jù)分析師已然成為企業(yè)挖掘數(shù)據(jù)價值、驅(qū)動決策的 ...
2025-07-15CDA 精益業(yè)務數(shù)據(jù)分析:驅(qū)動企業(yè)高效決策的核心引擎? 在數(shù)字經(jīng)濟時代,企業(yè)面臨著前所未有的數(shù)據(jù)洪流,如何從海量數(shù)據(jù)中提取有 ...
2025-07-15MySQL 無外鍵關聯(lián)表的 JOIN 實戰(zhàn):數(shù)據(jù)整合的靈活之道? 在 MySQL 數(shù)據(jù)庫的日常操作中,我們經(jīng)常會遇到需要整合多張表數(shù)據(jù)的場景 ...
2025-07-15Python Pandas:數(shù)據(jù)科學的瑞士軍刀? ? 在數(shù)據(jù)驅(qū)動的時代,面對海量、復雜的數(shù)據(jù),如何高效地進行處理、分析和挖掘成為關鍵。 ...
2025-07-15用 SQL 生成逆向回滾 SQL:數(shù)據(jù)操作的 “后悔藥” 指南? 在數(shù)據(jù)庫操作中,誤刪數(shù)據(jù)、錯改字段或誤執(zhí)行批量更新等問題時有發(fā)生。 ...
2025-07-14t檢驗與Wilcoxon檢驗的選擇:何時用t.test,何時用wilcox.test? t 檢驗與 Wilcoxon 檢驗的選擇:何時用 t.test,何時用 wilcox. ...
2025-07-14AI 浪潮下的生存與進階: CDA數(shù)據(jù)分析師—開啟新時代職業(yè)生涯的鑰匙(深度研究報告、發(fā)展指導白皮書) 發(fā)布機構(gòu):CDA數(shù)據(jù)科 ...
2025-07-13LSTM 模型輸入長度選擇技巧:提升序列建模效能的關鍵? 在循環(huán)神經(jīng)網(wǎng)絡(RNN)家族中,長短期記憶網(wǎng)絡(LSTM)憑借其解決長序列 ...
2025-07-11CDA 數(shù)據(jù)分析師報考條件詳解與準備指南? ? 在數(shù)據(jù)驅(qū)動決策的時代浪潮下,CDA 數(shù)據(jù)分析師認證愈發(fā)受到矚目,成為眾多有志投身數(shù) ...
2025-07-11數(shù)據(jù)透視表中兩列相乘合計的實用指南? 在數(shù)據(jù)分析的日常工作中,數(shù)據(jù)透視表憑借其強大的數(shù)據(jù)匯總和分析功能,成為了 Excel 用戶 ...
2025-07-11尊敬的考生: 您好! 我們誠摯通知您,CDA Level I和 Level II考試大綱將于 2025年7月25日 實施重大更新。 此次更新旨在確保認 ...
2025-07-10BI 大數(shù)據(jù)分析師:連接數(shù)據(jù)與業(yè)務的價值轉(zhuǎn)化者? ? 在大數(shù)據(jù)與商業(yè)智能(Business Intelligence,簡稱 BI)深度融合的時代,BI ...
2025-07-10SQL 在預測分析中的應用:從數(shù)據(jù)查詢到趨勢預判? ? 在數(shù)據(jù)驅(qū)動決策的時代,預測分析作為挖掘數(shù)據(jù)潛在價值的核心手段,正被廣泛 ...
2025-07-10