深度優(yōu)先與廣度優(yōu)先Java實(shí)現(xiàn)代碼示例
在編程生活中,我們總會(huì)遇見樹性結(jié)構(gòu),這幾天剛好需要對(duì)樹形結(jié)構(gòu)操作,就記錄下自己的操作方式以及過(guò)程?,F(xiàn)在假設(shè)有一顆這樣樹,(是不是二叉樹都沒(méi)關(guān)系,原理都是一樣的)
1、深度優(yōu)先
英文縮寫為DFS即Depth First Search.
深度優(yōu)先搜索是一種在開發(fā)爬蟲早期使用較多的方法。它的目的是要達(dá)到被搜索結(jié)構(gòu)的葉結(jié)點(diǎn)(即那些不包含任何超鏈的HTML文件) 。在一個(gè)HTML文件中,當(dāng)一個(gè)超鏈被選擇后,被鏈接的HTML文件將執(zhí)行深度優(yōu)先搜索,即在搜索其余的超鏈結(jié)果之前必須先完整地搜索單獨(dú)的一條鏈。深度優(yōu)先搜索沿著HTML文件上的超鏈走到不能再深入為止,然后返回到某一個(gè)HTML文件,再繼續(xù)選擇該HTML文件中的其他超鏈。當(dāng)不再有其他超鏈可選擇時(shí),說(shuō)明搜索已經(jīng)結(jié)束。其過(guò)程簡(jiǎn)要來(lái)說(shuō)是對(duì)每一個(gè)可能的分支路徑深入到不能再深入為止,而且每個(gè)節(jié)點(diǎn)只能訪問(wèn)一次。對(duì)于上面的例子來(lái)說(shuō)深度優(yōu)先遍歷的結(jié)果就是:A,B,D,E,I,C,F,G,H.(假設(shè)先走子節(jié)點(diǎn)的的左側(cè))。
深度優(yōu)先遍歷各個(gè)節(jié)點(diǎn),需要使用到堆(Stack)這種數(shù)據(jù)結(jié)構(gòu)。stack的特點(diǎn)是是先進(jìn)后出。整個(gè)遍歷過(guò)程如下:
首先將A節(jié)點(diǎn)壓入堆中,stack(A);
將A節(jié)點(diǎn)彈出,同時(shí)將A的子節(jié)點(diǎn)C,B壓入堆中,此時(shí)B在堆的頂部,stack(B,C);
將B節(jié)點(diǎn)彈出,同時(shí)將B的子節(jié)點(diǎn)E,D壓入堆中,此時(shí)D在堆的頂部,stack(D,E,C);
將D節(jié)點(diǎn)彈出,沒(méi)有子節(jié)點(diǎn)壓入,此時(shí)E在堆的頂部,stack(E,C);
將E節(jié)點(diǎn)彈出,同時(shí)將E的子節(jié)點(diǎn)I壓入,stack(I,C);
...依次往下,最終遍歷完成,Java代碼大概如下:
public void depthFirst() { Stack<Map<String, Object>> nodeStack = new Stack<Map<String, Object>>(); Map<String, Object> node = new HashMap<String, Object>(); nodeStack.add(node); while (!nodeStack.isEmpty()) { node = nodeStack.pop(); System.out.println(node); //獲得節(jié)點(diǎn)的子節(jié)點(diǎn),對(duì)于二叉樹就是獲得節(jié)點(diǎn)的左子結(jié)點(diǎn)和右子節(jié)點(diǎn) List<Map<String, Object>> children = getChildren(node); if (children != null && !children.isEmpty()) { for (Map child : children) { nodeStack.push(child); } } } } //節(jié)點(diǎn)使用Map存放
2、廣度優(yōu)先
英文縮寫為BFS即Breadth FirstSearch。其過(guò)程檢驗(yàn)來(lái)說(shuō)是對(duì)每一層節(jié)點(diǎn)依次訪問(wèn),訪問(wèn)完一層進(jìn)入下一層,而且每個(gè)節(jié)點(diǎn)只能訪問(wèn)一次。對(duì)于上面的例子來(lái)說(shuō),廣度優(yōu)先遍歷的 結(jié)果是:A,B,C,D,E,F,G,H,I(假設(shè)每層節(jié)點(diǎn)從左到右訪問(wèn))。
廣度優(yōu)先遍歷各個(gè)節(jié)點(diǎn),需要使用到隊(duì)列(Queue)這種數(shù)據(jù)結(jié)構(gòu),queue的特點(diǎn)是先進(jìn)先出,其實(shí)也可以使用雙端隊(duì)列,區(qū)別就是雙端隊(duì)列首位都可以插入和彈出節(jié)點(diǎn)。整個(gè)遍歷過(guò)程如下:
首先將A節(jié)點(diǎn)插入隊(duì)列中,queue(A);
將A節(jié)點(diǎn)彈出,同時(shí)將A的子節(jié)點(diǎn)B,C插入隊(duì)列中,此時(shí)B在隊(duì)列首,C在隊(duì)列尾部,queue(B,C);
將B節(jié)點(diǎn)彈出,同時(shí)將B的子節(jié)點(diǎn)D,E插入隊(duì)列中,此時(shí)C在隊(duì)列首,E在隊(duì)列尾部,queue(C,D,E);
將C節(jié)點(diǎn)彈出,同時(shí)將C的子節(jié)點(diǎn)F,G,H插入隊(duì)列中,此時(shí)D在隊(duì)列首,H在隊(duì)列尾部,queue(D,E,F(xiàn),G,H);
將D節(jié)點(diǎn)彈出,D沒(méi)有子節(jié)點(diǎn),此時(shí)E在隊(duì)列首,H在隊(duì)列尾部,queue(E,F(xiàn),G,H);
...依次往下,最終遍歷完成,Java代碼大概如下:
public void breadthFirst() { Deque
總結(jié)
以上就是本文關(guān)于深度優(yōu)先與廣度優(yōu)先Java實(shí)現(xiàn)代碼示例的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對(duì)本站的支持!
相關(guān)文章
spring-boot-maven-plugin:打包時(shí)排除provided依賴問(wèn)題
這篇文章主要介紹了spring-boot-maven-plugin:打包時(shí)排除provided依賴問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04Java線程休眠_(dá)動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
sleep() 的作用是讓當(dāng)前線程休眠,即當(dāng)前線程會(huì)從“運(yùn)行狀態(tài)”進(jìn)入到“休眠(阻塞)狀態(tài)”。下面通過(guò)實(shí)例代碼給大家介紹Java線程休眠的知識(shí),需要的朋友參考下吧2017-05-05Java設(shè)計(jì)模式之Builder建造者模式
這篇文章主要為大家詳細(xì)介紹了Java設(shè)計(jì)模式之Builder建造者模式的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03java如何獲取兩個(gè)List集合之間的交集、差集、并集
在日常開發(fā)中經(jīng)常會(huì)遇到對(duì)2個(gè)集合的操作,例如2個(gè)集合之間取相同的元素(交集),2個(gè)集合之間取不相同的元素(差集)等等,這篇文章主要給大家介紹了關(guān)于java如何獲取兩個(gè)List集合之間的交集、差集、并集的相關(guān)資料,需要的朋友可以參考下2024-02-02Java異常詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
異常是Java語(yǔ)言中的一部分,它代表程序中由各種原因引起的“不正常”因素。下面通過(guò)本文給大家介紹java異常的相關(guān)知識(shí),感興趣的朋友一起看看吧2017-06-06