日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > HTML >内容正文

HTML

一文了解树在前端中的应用,掌握数据结构中树的生命线

發(fā)布時(shí)間:2023/12/4 HTML 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一文了解树在前端中的应用,掌握数据结构中树的生命线 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一文了解樹在前端中的應(yīng)用

  • 🏕?序言
  • 🌲一、樹是什么?
  • 🌴二、深/廣度優(yōu)先遍歷
    • 1、深度優(yōu)先遍歷
      • (1)定義
      • (2)口訣
      • (3)代碼實(shí)現(xiàn)
    • 2、廣度優(yōu)先遍歷
      • (1)定義
      • (2)口訣
      • (3)代碼實(shí)現(xiàn)
  • 🌱三、二叉樹
    • 1、定義
    • 2、二叉樹的先/中/后序遍歷
      • (1)先序遍歷
      • (2)中序遍歷
      • (3)后序遍歷
    • 3、JS實(shí)現(xiàn)先中后序三種遍歷
      • (1)JS實(shí)現(xiàn)二叉樹的先序遍歷
      • (2)JS實(shí)現(xiàn)二叉樹的中序遍歷
      • (3)JS實(shí)現(xiàn)二叉樹的后序遍歷
      • (4)總結(jié)
  • ??四、leetcode經(jīng)典題目剖析
    • 1、leetcode104二叉樹的最大深度(簡(jiǎn)單)
    • 2、leetcode111二叉樹的最小深度(簡(jiǎn)單)
    • 3、leetcode102二叉樹的層序遍歷(中等)
    • 4、leetcode94二叉樹的中序遍歷(簡(jiǎn)單)
    • 5、leetcode112路徑總和(簡(jiǎn)單)
    • 6、leetcode129求根節(jié)點(diǎn)到葉節(jié)點(diǎn)數(shù)字之和(中等)
  • 🎄五、前端與樹:遍歷JSON的所有節(jié)點(diǎn)值
    • 1、碎碎念
    • 2、代碼實(shí)現(xiàn)
      • (1)制造數(shù)據(jù)
      • (2)遍歷節(jié)點(diǎn)值
      • (3)打印結(jié)果
  • 🏡六、結(jié)束語
  • 🐣彩蛋One More Thing
    • (:往期推薦
    • (:番外篇

🏕?序言

在我們的日常生活中,無時(shí)無刻都會(huì)看到樹。比如,在街上行走時(shí),就有著一排排的樹。那么,樹在前端中,都有哪些應(yīng)用呢?

事實(shí)上,前端在寫頁(yè)面時(shí),每個(gè)頁(yè)面就有它對(duì)應(yīng)的 DOM 樹、 CSSOM 樹等等。除此之外呢,像我們寫級(jí)聯(lián)選擇器時(shí),它也是一層疊一層的,就像一棵樹一樣。

在接下來的這篇文章中,將講解樹這個(gè)數(shù)據(jù)結(jié)構(gòu)的一些基本操作,以及樹在前端中的應(yīng)用。

一起來學(xué)習(xí)叭~🧐

🌲一、樹是什么?

  • 樹是一種具有分層數(shù)據(jù)功能的抽象模型。
  • 前端工作中常用的樹包括: DOM 樹、級(jí)聯(lián)選擇、樹形空間……。
  • JS 中沒有樹,但是可以用 Object 和 Array 構(gòu)建樹。
  • 樹的常用操作:深度/廣度優(yōu)先遍歷、先中后序遍歷。

🌴二、深/廣度優(yōu)先遍歷

1、深度優(yōu)先遍歷

(1)定義

  • 深度優(yōu)先遍歷,即盡可能深的搜索樹的分支。

(2)口訣

  • 訪問根節(jié)點(diǎn)。
  • 對(duì)根節(jié)點(diǎn)的 children 挨個(gè)進(jìn)行深度優(yōu)先遍歷。

(3)代碼實(shí)現(xiàn)

接下來用 JS 來實(shí)現(xiàn)樹的深度優(yōu)先遍歷。具體代碼如下:

const tree = {val:'a',children:[{val:'b',children:[{val:'d',children:[]},{val:'e',children:[]}]},{val:'c',children:[{val:'f',children:[]},{val:'a',children:[]}]}] }const dfs = (root) => {console.log(root.val);// 使用遞歸root.children.forEach(dfs); }/* 打印結(jié)果: a b d e c f a */

通過以上代碼我們可以知道,首先我們先定義一棵樹 tree ,之后使用遞歸的方法,對(duì)樹的 Children 挨個(gè)進(jìn)行遍歷,最終得到 abdecfa 的打印結(jié)果。

這個(gè)順序怎么理解會(huì)更為容易一點(diǎn)呢?

在上面的知識(shí)點(diǎn)我們談到,樹是往深了遍歷。那在我們這道題的 tree 樹當(dāng)中,我們總得先對(duì)第一層的遍歷完,才能遍歷第二層的。而第一層的內(nèi)容又有很多層,那就先把它往深了遍歷,等到第一層的深度遍歷結(jié)束后,我們才開始遍歷第二層的。

所以,我們先在來看一下,最上面的是 a ,接著就是第一層,第一層有 bde ,接下來是第二層,第二層就有 cfa 。因此,最終的順序?yàn)?abdecfa 。

2、廣度優(yōu)先遍歷

(1)定義

  • 廣度優(yōu)先遍歷,即先訪問根節(jié)點(diǎn)最近的節(jié)點(diǎn)

(2)口訣

  • 新建一個(gè)隊(duì)列。
  • 把隊(duì)頭出隊(duì)并訪問。
  • 把隊(duì)頭的 children 挨個(gè)入隊(duì)。
  • 重復(fù)第二步和第三步,直到隊(duì)列為空。

(3)代碼實(shí)現(xiàn)

接下來用 JS 來實(shí)現(xiàn)樹的廣度優(yōu)先遍歷。具體代碼如下:

const tree = {val:'a',children:[{val:'b',children:[{val:'d',children:[]},{val:'e',children:[]}]},{val:'c',children:[{val:'f',children:[]},{val:'a',children:[]}]}] }const bfs = (root) => {// 新建一個(gè)隊(duì)列,并把根節(jié)點(diǎn)先放到隊(duì)列里面const q = [root];while(q.length > 0){// 不斷進(jìn)行出隊(duì),訪問const n = q.shift();// 邊出隊(duì)邊訪問console.log(n.val);// 把隊(duì)頭的children挨個(gè)入隊(duì),退到隊(duì)列里面n.children.forEach(child => {q.push(child);});} }bfs(tree);/* 打印結(jié)果: a b c d e f a */

🌱三、二叉樹

1、定義

  • 對(duì)于二叉樹來說,樹中的每個(gè)節(jié)點(diǎn)最多只能有兩個(gè)子節(jié)點(diǎn)
  • JS 中沒有二叉樹,但通常用對(duì)象 Object 模擬二叉樹。

2、二叉樹的先/中/后序遍歷

(1)先序遍歷

  • 訪問根節(jié)點(diǎn)。
  • 對(duì)根節(jié)點(diǎn)的左子樹進(jìn)行先序遍歷。
  • 對(duì)根節(jié)點(diǎn)的右子樹進(jìn)行先序遍歷。

(2)中序遍歷

  • 對(duì)根節(jié)點(diǎn)的左子樹進(jìn)行中序遍歷。
  • 訪問根節(jié)點(diǎn)。
  • 對(duì)根節(jié)點(diǎn)的右子樹進(jìn)行中序遍歷。

(3)后序遍歷

  • 對(duì)根節(jié)點(diǎn)的左子樹進(jìn)行后序遍歷。

  • 對(duì)根節(jié)點(diǎn)的右子樹進(jìn)行后序遍歷。

  • 訪問根節(jié)點(diǎn)。

3、JS實(shí)現(xiàn)先中后序三種遍歷

下面我們用代碼來實(shí)現(xiàn)二叉樹的這三種遍歷。接下來開始講解~

(1)JS實(shí)現(xiàn)二叉樹的先序遍歷

對(duì)于二叉樹的先序遍歷來說,是先訪問根節(jié)點(diǎn),之后再訪問左子樹,最后訪問右子樹。下面我們用兩種方式來實(shí)現(xiàn)先序遍歷,第一種是遞歸版本,第二種是非遞歸版本

先定義一棵樹:

const bt = {val:1,left:{val:2,left:{val:4,left:null,right:null},right:{val:5,left:null,right:null}},right:{val:3,left:{val:6,left:null,right:null},right:{val:7,left:null,right:null}} }

遞歸版本實(shí)現(xiàn):

// 遞歸版本實(shí)現(xiàn) const preOrder1 = (root) => {if(!root){return;}console.log(root.val);preOrder1(root.left);preOrder1(root.right); }preOrder1(bt); /**打印結(jié)果: 1 2 4 5 3 6 7 */

非遞歸版本實(shí)現(xiàn):

// 非遞歸版實(shí)現(xiàn) /*** 思路:* 1.新建一個(gè)棧模擬函數(shù)的調(diào)用堆棧;* 2.對(duì)于先序遍歷來說,需要先把根節(jié)點(diǎn)取出,然后再遍歷左子樹了右子樹;* 3.按照棧的先進(jìn)后出特點(diǎn),先把右子樹放進(jìn)棧里,再把左子樹放進(jìn)棧里,一一取出。*/ const preOrder2 = (root) => {if(!root){return;}// 新建一個(gè)stack代表函數(shù)的調(diào)用堆棧const stack = [root];// console.log(stack)while(stack.length){// 將根節(jié)點(diǎn)從棧里彈出const n = stack.pop();console.log(n.val);if(n.right){stack.push(n.right);}if(n.left){stack.push(n.left);}} }preOrder2(bt); /**打印結(jié)果: 1 2 4 5 3 6 7 */

(2)JS實(shí)現(xiàn)二叉樹的中序遍歷

對(duì)于二叉樹的中序遍歷來說,是先訪問子樹,之后訪問節(jié)點(diǎn),最后再訪問子樹。下面我們用兩種方式來實(shí)現(xiàn)中序遍歷,第一種是遞歸版本,第二種是非遞歸版本

同樣地,我們先來先定義一棵樹:

const bt = {val:1,left:{val:2,left:{val:4,left:null,right:null},right:{val:5,left:null,right:null}},right:{val:3,left:{val:6,left:null,right:null},right:{val:7,left:null,right:null}} }

遞歸版本實(shí)現(xiàn):

// 遞歸版本實(shí)現(xiàn) const inOrder1 = (root) => {if(!root){return;}inOrder(root.left);console.log(root.val);inOrder(root.right); }inOrder1(bt); /**打印結(jié)果: 4 2 5 1 6 3 7 */

非遞歸版本實(shí)現(xiàn):

// 非遞歸版實(shí)現(xiàn) /*** 思路:* 1.新建一個(gè)棧模擬函數(shù)的調(diào)用堆棧;* 2.對(duì)于中序遍歷來說,需要先把左子樹全部丟到棧里面;那么需要每當(dāng)遍歷一個(gè),就推到棧里面* 3.遍歷完成之后,把最盡頭的結(jié)點(diǎn)彈出,并訪問它;此處最盡頭的結(jié)點(diǎn)即盡頭出的根節(jié)點(diǎn),左根右* 4.訪問完左結(jié)點(diǎn)后,需要訪問右結(jié)點(diǎn);*/ const inOrder2 = (root) => {if(!root){return;}let p = root;const stack = [];while(p || stack.length){while(p){// 先進(jìn)棧stack.push(p);// 進(jìn)棧完繼續(xù)指向左子樹p = p.left;}// 彈出最后一個(gè)const n = stack.pop();console.log(n.val);p = n.right;}}inOrder2(bt); /**打印結(jié)果: 4 2 5 1 6 3 7 */

(3)JS實(shí)現(xiàn)二叉樹的后序遍歷

對(duì)于二叉樹的后序遍歷來說,是先訪問子樹,之后訪問子樹,最后再訪問節(jié)點(diǎn)。下面我們用兩種方式來實(shí)現(xiàn)后序遍歷,第一種是遞歸版本,第二種是非遞歸版本

首先同樣地,先來定義一棵樹:

const bt = {val:1,left:{val:2,left:{val:4,left:null,right:null},right:{val:5,left:null,right:null}},right:{val:3,left:{val:6,left:null,right:null},right:{val:7,left:null,right:null}} }

遞歸版本實(shí)現(xiàn):

// 遞歸版本實(shí)現(xiàn) const postOrder1 = (root) => {if(!root){return;}postOrder1(root.left);postOrder1(root.right);console.log(root.val); }preOrder1(bt); /**打印結(jié)果: 1 2 4 5 3 6 7 */

非遞歸版本實(shí)現(xiàn):

// 非遞歸版實(shí)現(xiàn) /*** 思路:* 1.建立一個(gè)空棧stack;* 2.分別把左子樹,右子樹分別放入stack棧* 3.建立一個(gè)倒序棧outputStack,先把根樹放進(jìn),再一一放入右子樹,右子樹全部放完之后再放左子樹*/ const postOrder2 = (root) => {if(!root){return;}// 倒序棧輸出,放根右左的順序,之后再一一取出const outputStack = [];// 先放左子樹,再放右子樹,方便后面取出const stack = [root];while(stack.length){const n = stack.pop();outputStack.push(n);if(n.left){stack.push(n.left);}if(n.right){stack.push(n.right);}}while(outputStack.length){const n = outputStack.pop();console.log(n.val);} } preOrder2(bt); /**打印結(jié)果: 1 2 4 5 3 6 7 */

(4)總結(jié)

看完上面的代碼實(shí)現(xiàn)后,我們來做個(gè)總結(jié)。為什么這里要展示遞歸版本和非遞歸版本呢?

事實(shí)上,在我們的日常開發(fā)中,遞歸遍歷是非常常見的。但試想一下,有時(shí)候我們的業(yè)務(wù)邏輯有可能很復(fù)雜,那這個(gè)時(shí)候前端從后端接收到的數(shù)據(jù)量是比較大的。這個(gè)時(shí)候如果用遞歸版本來處理的話,算法復(fù)雜度相對(duì)來說就會(huì)比較高了。

所以我們多了一種非遞歸版本的實(shí)現(xiàn)方式,非遞歸版本的實(shí)現(xiàn)方式,旨在以空間來?yè)Q時(shí)間,減少代碼的時(shí)間復(fù)雜度。

??四、leetcode經(jīng)典題目剖析

接下來我們引用幾道經(jīng)典的 leetcode 算法,來鞏固樹和二叉樹的知識(shí)。

1、leetcode104二叉樹的最大深度(簡(jiǎn)單)

(1)題意

附上題目鏈接:leetcode104二叉樹的最大深度

給定一個(gè)二叉樹,找出其最大深度。

二叉樹的深度為根節(jié)點(diǎn)到最遠(yuǎn)葉子節(jié)點(diǎn)的最長(zhǎng)路徑上的節(jié)點(diǎn)數(shù)。

說明: 葉子節(jié)點(diǎn)是指沒有子節(jié)點(diǎn)的節(jié)點(diǎn)。

輸入輸出示例:

  • 輸入: 給定二叉樹 [3,9,20,null,null,15,7]
  • 輸出: 3

(2)解題思路

  • 求最大深度,考慮使用深度優(yōu)先遍歷
  • 在深度優(yōu)先遍歷過程中,記錄每個(gè)節(jié)點(diǎn)所在的層級(jí),找出最大的層級(jí)即可。

(3)解題步驟

  • 新建一個(gè)變量,記錄最大深度。
  • 深度優(yōu)先遍歷整棵樹,并記錄每個(gè)節(jié)點(diǎn)的層級(jí),同時(shí)不斷刷新最大深度的這個(gè)變量。
  • 遍歷結(jié)束返回最大深度的變量。

(4)代碼實(shí)現(xiàn)

/*** @param {TreeNode} root* @return {number}*/ let maxDepth = function(root) {let res = 0;const dfs = (n, l) => {if(!n){return;}if(!n.left && !n.right){res = Math.max(res, l);}dfs(n.left, l + 1);dfs(n.right, l + 1);}dfs(root, 1);return res; }

2、leetcode111二叉樹的最小深度(簡(jiǎn)單)

(1)題意

附上題目鏈接:leetcode111二叉樹的最小深度

給定一個(gè)二叉樹,找出其最小深度。

最小深度是從根節(jié)點(diǎn)到最近葉子節(jié)點(diǎn)的最短路徑上的節(jié)點(diǎn)數(shù)量。

**說明:**葉子節(jié)點(diǎn)是指沒有子節(jié)點(diǎn)的節(jié)點(diǎn)。

輸入輸出示例:

  • 輸入: root = [3,9,20,null,null,15,7]
  • 輸出: 2

(2)解題思路

  • 求最小深度,考慮使用廣度優(yōu)先遍歷。
  • 在廣度優(yōu)先遍歷過程中,遇到葉子節(jié)點(diǎn),停止遍歷,返回節(jié)點(diǎn)層級(jí)。

(3)解題步驟

  • 廣度優(yōu)先遍歷整棵樹,并記錄每個(gè)節(jié)點(diǎn)的層級(jí)。
  • 遇到葉子節(jié)點(diǎn),返回節(jié)點(diǎn)層級(jí),停止遍歷。

(4)代碼實(shí)現(xiàn)

/*** @param {TreeNode} root* @return {number}*/let minDepth = function(root){if(!root){return 0;}const q = [[root, 1]];while(q.length){const [n, l] = q.shift();if(!n.left && !n.right){return l;}if(n.left){q.push([n.left, l + 1]);}if(n.right){q.push([n.right, l + 1]);}} }

3、leetcode102二叉樹的層序遍歷(中等)

(1)題意

附上題目鏈接:leetcode102二叉樹的層序遍歷

給你一個(gè)二叉樹,請(qǐng)你返回其按 層序遍歷 得到的節(jié)點(diǎn)值。 (即逐層地,從左到右訪問所有節(jié)點(diǎn))。

輸入輸出示例:

  • 輸入: 二叉樹:[3,9,20,null,null,15,7]

    3/ \9 20/ \15 7
  • 輸出:

    [[3],[9,20],[15,7] ]

(2)解題思路

  • 層序遍歷順序就是廣度優(yōu)先遍歷。
  • 不過在遍歷時(shí)候需要記錄當(dāng)前節(jié)點(diǎn)所處的層級(jí),方便將其添加到不同的數(shù)組中。

(3)解題步驟

  • 廣度優(yōu)先遍歷二叉樹。
  • 遍歷過程中,記錄每個(gè)節(jié)點(diǎn)的層級(jí),并將其添加到不同的數(shù)組中。

(4)代碼實(shí)現(xiàn)

/*** @param {TreeNode} root* @return {number[][]}*/ // 方法一 let levelOrder1 = function(root) {if(!root){return [];}const q = [[root, 0]];const res = [];while(q.length){const [n, level] = q.shift();if(!res[level]){// 沒有該層次的數(shù)組時(shí)先創(chuàng)建一個(gè)數(shù)組res.push([n.val]);}else{// 有數(shù)組時(shí)直接將值放進(jìn)res[level].push(n.val);}if(n.left){q.push([n.left, level + 1]);}if(n.right){q.push([n.right, level + 1]);}}return res; };// 方法二 let levelOrder2 = function(root){if(!root){return [];}const q = [root];const res = [];while(q.length){let len = q.length;res.push([]);while(len--){const n = q.shift();res[res.length - 1].push(n.val);if(n.left){q.push(n.left);}if(n.right){q.push(n.right);}}}return res; }

4、leetcode94二叉樹的中序遍歷(簡(jiǎn)單)

(1)題意

附上題目鏈接:leetcode94二叉樹的中序遍歷

給定一個(gè)二叉樹的根節(jié)點(diǎn) root ,返回它的 中序 遍歷。

輸入輸出示例:

  • 輸入: root = [1,null,2,3]
  • 輸出: [1,3,2]

(2)解題思路&&解題步驟

  • 這里的解題思路和步驟和上方講中序遍歷時(shí)類似,所以不再做講解,下面直接看代碼實(shí)現(xiàn)。

(3)代碼實(shí)現(xiàn)

/*** @param {TreeNode} root* @return {number[]}*/ // 遍歷版本let inorderTraversal1 = function(root) {const res = [];const rec = (n) => {if(!n){return;}rec(n.left);rec(n.val);rec(n.right);}rec(root);return res; };// 迭代版本——棧方法 let inorderTraversal2 = function(root){const res = [];const stack = [];let p = root;while(stack.length || p){while(p){stack.push(p);p = p.left;}const n = stack.pop();res.push(n.val);p = n.right;}return res; }inorderTraversal1(root); inorderTraversal2(root);

5、leetcode112路徑總和(簡(jiǎn)單)

(1)題意

附上題目鏈接:leetcode112路徑總和

給你二叉樹的根節(jié)點(diǎn) root 和一個(gè)表示目標(biāo)和的整數(shù) targetSum ,判斷該樹中是否存在 根節(jié)點(diǎn)到葉子節(jié)點(diǎn) 的路徑,這條路徑上所有節(jié)點(diǎn)值相加等于目標(biāo)和 targetSum 。

葉子節(jié)點(diǎn) 是指沒有子節(jié)點(diǎn)的節(jié)點(diǎn)。

輸入輸出示例:

  • 輸入: root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
  • 輸出: true

(2)解題思路

  • 在深度優(yōu)先遍歷的過程中,記錄當(dāng)前路徑思維節(jié)點(diǎn)值的和。
  • 在葉子節(jié)點(diǎn)處,判斷當(dāng)前路徑的節(jié)點(diǎn)值的和是否等于目標(biāo)值。

(3)解題步驟

  • 深度優(yōu)先遍歷二叉樹,在葉子節(jié)點(diǎn)處,判斷當(dāng)前路徑路徑的節(jié)點(diǎn)值的和是否等于目標(biāo)值,是就返回true。
  • 遍歷結(jié)束,如果沒有匹配,就返回false。

(4)代碼實(shí)現(xiàn)

/*** @param {TreeNode} root* @param {number} targetSum* @return {boolean}*/ // 遞歸法 let hasPathSum = function(root, targetSum) {if(!root){return false;}let res = false;const dfs = (n, s) => {if(!n.left && !n.right && s === targetSum){res = true;}if(n.left){dfs(n.left, s + n.left.val);}if(n.right){dfs(n.right, s + n.right.val);}}dfs(root, root.val);return res; };

6、leetcode129求根節(jié)點(diǎn)到葉節(jié)點(diǎn)數(shù)字之和(中等)

(1)題意

附上題目鏈接:leetcode129求根節(jié)點(diǎn)到葉節(jié)點(diǎn)數(shù)字之和

給你一個(gè)二叉樹的根節(jié)點(diǎn) root ,樹中每個(gè)節(jié)點(diǎn)都存放有一個(gè) 0 到 9 之間的數(shù)字。

每條從根節(jié)點(diǎn)到葉節(jié)點(diǎn)的路徑都代表一個(gè)數(shù)字:

例如,從根節(jié)點(diǎn)到葉節(jié)點(diǎn)的路徑 1 -> 2 -> 3 表示數(shù)字 123 。

計(jì)算從根節(jié)點(diǎn)到葉節(jié)點(diǎn)生成的 所有數(shù)字之和

葉節(jié)點(diǎn) 是指沒有子節(jié)點(diǎn)的節(jié)點(diǎn)。

輸入輸出示例:

  • 輸入: root = [1,2,3]
  • 輸出: 25
  • 解釋:
    • 從根到葉子節(jié)點(diǎn)路徑 1->2 代表數(shù)字 12
    • 從根到葉子節(jié)點(diǎn)路徑 1->3 代表數(shù)字 13
    • 因此,數(shù)字總和 = 12 + 13 = 25

(2)解題思路

  • 在深度優(yōu)先遍歷的過程中,記錄當(dāng)前路徑前面節(jié)點(diǎn)的值。
  • 在葉子節(jié)點(diǎn)處,計(jì)算出當(dāng)前路徑值。

(3)解題步驟

  • 深度優(yōu)先遍歷二叉樹,直到每一棵樹的葉子節(jié)點(diǎn)處結(jié)束。
  • 遍歷結(jié)束,返回所有路徑值。

(4)代碼實(shí)現(xiàn)

/*** @param {TreeNode} root* @return {number}*/var sumNumbers = function(root) {// 深度優(yōu)先遍歷處理const dfs = (n, preNum) => {if(!n){return 0;}const sum = preNum * 10 + n.val;if(!n.left && !n.right){return sum;}else{return dfs(n.left, sum) + dfs(n.right, sum);}}return dfs(root, 0); };

🎄五、前端與樹:遍歷JSON的所有節(jié)點(diǎn)值

1、碎碎念

有時(shí)候,后端傳過來的數(shù)據(jù)可能不是很友好,有可能一串?dāng)?shù)據(jù)里面又是對(duì)象又是數(shù)組的,這個(gè)時(shí)候前端拿到數(shù)據(jù)后,就需要稍微處理一下了。

因此,我們可以通過深度優(yōu)先遍歷來遍歷 JSON 中的所有節(jié)點(diǎn)值。

接下來用一個(gè)例子來展示~

2、代碼實(shí)現(xiàn)

(1)制造數(shù)據(jù)

假設(shè)我們心在有一串 json 的數(shù)據(jù),代碼如下:

const json = {a:{b:{c:1}},d:[1, 2] }

(2)遍歷節(jié)點(diǎn)值

接下來,我們用深度優(yōu)先遍歷的方式,來遍歷 JSON 中的所有節(jié)點(diǎn)值。具體實(shí)現(xiàn)代碼如下:

const dfs = (n, path) => {console.log(n, path);Object.keys(n).forEach(k => {dfs(n[k], path.concat(k));}); };dfs(json, []);

(3)打印結(jié)果

最終打印結(jié)果如下:

{ a: { b: { c: 1 } }, d: [ 1, 2 ] } [] { b: { c: 1 } } [ 'a' ] { c: 1 } [ 'a', 'b' ] 1 [ 'a', 'b', 'c' ] [ 1, 2 ] [ 'd' ] 1 [ 'd', '0' ] 2 [ 'd', '1' ]

大家看上面的打印結(jié)果可以發(fā)現(xiàn),通過深度優(yōu)先遍歷的方式,數(shù)據(jù)都被一一遍歷出來。因此,對(duì)于樹這種數(shù)據(jù)結(jié)構(gòu)來說,在前端當(dāng)中出現(xiàn)的頻率也是較高的~~

🏡六、結(jié)束語

通過上文的學(xué)習(xí),我們了解了樹的兩種遍歷:深度優(yōu)先遍歷和廣度優(yōu)先遍歷。同時(shí),還有一種特殊的樹,二叉樹。二叉樹在面試中,基本上是一大必考點(diǎn)。對(duì)于二叉樹來說,要了解它的三種遍歷方式:先序、中序和后序遍歷,并且要掌握好這三者之間的區(qū)別以及常見的應(yīng)用場(chǎng)景。

關(guān)于樹在前端中的應(yīng)用講到這里就結(jié)束啦!希望對(duì)大家有幫助~

如有疑問或文章有誤歡迎評(píng)論區(qū)留言或公眾號(hào)后臺(tái)加我微信提問~

🐣彩蛋One More Thing

(:往期推薦

棧👉棧在前端中的應(yīng)用,順便再了解下深拷貝和淺拷貝!

隊(duì)列👉詳解隊(duì)列在前端的應(yīng)用,深剖JS中的事件循環(huán)Eventloop,再了解微任務(wù)和宏任務(wù)

鏈表👉詳解鏈表在前端的應(yīng)用,順便再弄懂原型和原型鏈!

字典和集合👉ES6的Set和Map你都知道嗎?一文了解集合和字典在前端中的應(yīng)用

動(dòng)態(tài)規(guī)則和分而治之算法👉一文了解分而治之和動(dòng)態(tài)規(guī)則算法在前端中的應(yīng)用

貪心算法和回溯算法👉一文了解貪心算法和回溯算法在前端中的應(yīng)用

(:番外篇

  • 關(guān)注公眾號(hào)星期一研究室,第一時(shí)間關(guān)注學(xué)習(xí)干貨,更多精選專欄待你解鎖~
  • 如果這篇文章對(duì)你有用,記得留個(gè)腳印jio再走哦~
  • 以上就是本文的全部?jī)?nèi)容!我們下期見!👋👋👋

總結(jié)

以上是生活随笔為你收集整理的一文了解树在前端中的应用,掌握数据结构中树的生命线的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。