可視化講解 深度優(yōu)先遍歷(DFT)

打個小廣告:
如果你想獲取更多前端干貨、鵝廠工程師的前端面試指南,
歡迎關(guān)注我的個人微信公眾號:
前端夜談

深度優(yōu)先遍歷, 刷過題的朋友應該都很熟悉了,難是不難,但是理解起來還是要費一些功夫的. 深度優(yōu)先遍歷的實現(xiàn)方法有遞歸非遞歸兩種, 這里我們用可視化的角度,講解前一種: 遞歸的深度優(yōu)先遍歷.

為什么要以可視化的方式來講解呢? 因為人是視覺的動物, 如果和你說 二叉樹 , 相信大家腦中出現(xiàn)的都是下面的圖形:

binary tree
stack

而不是下面的代碼:

// binary tree
class Node {
  constructor(value, leftChild, rightChild) {
    this.value = value
    this.leftChild = leftChild
    this.rightChild = rightChild
  }
}

// stack
const stack = new Array()
stack.push(1)
var topItem = stack.pop()

所以說, 人是視覺動物, 以圖形可視化的方式來講解問題往往能講解的更清楚, 這也就是我寫本文的緣由.

效果展示

為了可視化的講解 深度優(yōu)先遍歷算法, 筆者寫了一個簡單的網(wǎng)頁, 實現(xiàn)的功能有:

  • 用戶可編輯進行深度遍歷的二叉樹
  • 網(wǎng)頁上給出了 JavaScript 版本的實現(xiàn)
  • 點擊 Start DFT 按鈕, 用戶將看到算法中用到的 二叉樹 都將動態(tài) 的展示在頁面中,可以直觀的看到代碼運行過程中數(shù)據(jù)的變化

頁面目前還在繼續(xù)優(yōu)化中攒岛, 讓我們看看目前的效果:

在線demo:

https://ssthouse.github.io/visual-explain/#/list/dft

stack

可以看到,網(wǎng)頁模擬了深度搜索時二叉樹的動態(tài)變化過程:

  • 二叉樹中當前遍歷到的節(jié)點會變成紅色;
  • 棧中壓入 (push)的節(jié)點為灰色;
  • 棧中彈出 (pop) 的節(jié)點會變?yōu)?em>紅色炎疆, 然后消失;

其中頁面左上角為初始遍歷的二叉樹數(shù)據(jù)考阱, 用戶可以修改二叉樹數(shù)據(jù)后再次啟動可視化深度優(yōu)先遍歷過程.

頁面左下角為深度優(yōu)先遍歷的 javascript 實現(xiàn)版本,作為參考.

深度優(yōu)先遍歷簡介

可視化分析之前粘姜,讓我們先來簡單看看實現(xiàn)深度優(yōu)先搜索的代碼:

export class Dft {
  constructor(rootNode, stepCallback) {
    this.rootNode = rootNode
    this.stepCallback = stepCallback
  }

  start() {
    if (!this.rootNode || !this.stepCallback) {
      return
    }
    const stack = [this.rootNode]
    while (stack.length !== 0) {
      const curNode = stack.pop()
      console.log(`current node: ${curNode.value}`)
      curNode.childrenNodes.forEach(element => {
        stack.push(element)
      })
    }
  }
}

export class Node {
  constructor(value, childrenNodes = []) {
    this.value = value
    this.childrenNodes = childrenNodes
  }
}

代碼不長鬓照,讓我們一步步看.

首先我們創(chuàng)建了一個棧 const stack = [this.rootNode] , 并將根節(jié)點放入棧中.

接下來是一個while語句, 跳出循環(huán)的條件是 棧為空, 也就是代表我們遍歷完了整棵樹.

在循環(huán)中, 我們先將棧頂?shù)墓?jié)點彈出, 并打印出來, 表示我們已經(jīng)遍歷過了該節(jié)點. 然后將該節(jié)點的所有子節(jié)點壓入棧中, 這就保障了我們下一個遍歷到的點就是該節(jié)點的子節(jié)點. 重復該循環(huán), 最后我們就可以看到, 二叉樹的每個節(jié)點都按照深度搜索的順序被打印了出來:

current node: 1
current node: 4
current node: 7
current node: 6
current node: 2
current node: 5
current node: 3

如果是對棧的使用比較熟悉的同學, 可能看到這里就已經(jīng)明白原理了.

但是, 如果是對棧使用不是很熟悉的同學, 估計對代碼的執(zhí)行過程還是沒有一個直觀的認識, 那么讓我們以更直觀的方式看看這段代碼是怎么運行的.

可視化講解

第一步, 將根節(jié)點壓入棧中:

step1

接下來進入 while 循環(huán), 每個循環(huán)都會將棧頂?shù)墓?jié)點彈出, 將其子節(jié)點壓入棧中:

step2

可以看出, 深度優(yōu)先遍歷利用了棧先進后出的特性, 使得對于每個節(jié)點, 都將在遍歷該節(jié)點后,下一步遍歷他的子節(jié)點, 由此完成深度優(yōu)先的遍歷:

stack

最后

本文中的二叉樹, 的可視化是筆者自己封裝的 UI 組件, 只需簡單的調(diào)用就可以將代碼中數(shù)據(jù)結(jié)構(gòu)以可視化的方式顯示在頁面中.

個人覺得這樣的數(shù)據(jù)結(jié)構(gòu)可視化可能會對代碼的講解有些幫助, 如果你也有這方面的需求的話, 不妨在下面留言告訴我, 我可以將這些 UI 組件封裝一下方便有需要的人使用.

源碼在這, 歡迎 fork & star

https://github.com/ssthouse/visual-explain

想繼續(xù)了解 D3.js || 數(shù)據(jù)可視化 ?

這里是我的 D3.js數(shù)據(jù)可視化 的 github 地址, 歡迎 start & fork :tada:

D3-blog

如果覺得不錯的話, 不妨點擊下面的鏈接關(guān)注一下 : )

github 主頁

知乎專欄

掘金

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末孤紧,一起剝皮案震驚了整個濱河市豺裆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌号显,老刑警劉巖臭猜,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異押蚤,居然都是意外死亡蔑歌,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門揽碘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來次屠,“玉大人,你說我怎么就攤上這事雳刺〗僭睿” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵掖桦,是天一觀的道長本昏。 經(jīng)常有香客問我,道長枪汪,這世上最難降的妖魔是什么涌穆? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任怔昨,我火速辦了婚禮,結(jié)果婚禮上蒲犬,老公的妹妹穿的比我還像新娘朱监。我一直安慰自己,他們只是感情好原叮,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布赫编。 她就那樣靜靜地躺著,像睡著了一般奋隶。 火紅的嫁衣襯著肌膚如雪擂送。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天唯欣,我揣著相機與錄音嘹吨,去河邊找鬼。 笑死境氢,一個胖子當著我的面吹牛蟀拷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播萍聊,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼问芬,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了寿桨?” 一聲冷哼從身側(cè)響起此衅,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎亭螟,沒想到半個月后挡鞍,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡预烙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年墨微,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扁掸。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡欢嘿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出也糊,到底是詐尸還是另有隱情,我是刑警寧澤羡宙,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布狸剃,位于F島的核電站,受9級特大地震影響狗热,放射性物質(zhì)發(fā)生泄漏钞馁。R本人自食惡果不足惜虑省,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望僧凰。 院中可真熱鬧探颈,春花似錦、人聲如沸训措。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绩鸣。三九已至怀大,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間呀闻,已是汗流浹背化借。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留捡多,地道東北人蓖康。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像垒手,于是被迫代替她去往敵國和親蒜焊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容