JavaScript實(shí)現(xiàn)樹(shù)結(jié)構(gòu)轉(zhuǎn)換的五種方法總結(jié)
在 JavaScript 編程中,將數(shù)組轉(zhuǎn)換為樹(shù)結(jié)構(gòu)是一個(gè)常見(jiàn)的需求。本篇博客將介紹五種常用的方法來(lái)實(shí)現(xiàn)數(shù)組轉(zhuǎn)樹(shù)結(jié)構(gòu),并討論每種方法的時(shí)間復(fù)雜度、空間復(fù)雜度和最優(yōu)解。
假設(shè)有一個(gè)由對(duì)象組成的數(shù)組,每個(gè)對(duì)象包含 id
和 parentId
兩個(gè)屬性。其中 id
表示節(jié)點(diǎn)的唯一標(biāo)識(shí),parentId
表示該節(jié)點(diǎn)的父節(jié)點(diǎn)的 id
。
const nodes = [ { id: 1, parentId: null }, { id: 2, parentId: 1 }, { id: 3, parentId: 1 }, { id: 4, parentId: 2 }, { id: 5, parentId: 3 }, { id: 6, parentId: 3 }, { id: 7, parentId: 4 }, { id: 8, parentId: 4 }, ];
以上面的數(shù)組為例,我們將介紹以下五種方法來(lái)將其轉(zhuǎn)換為樹(shù)結(jié)構(gòu)。
方法一:使用遞歸
function arrayToTreeRec(nodes, parentId = null) { return nodes .filter((node) => node.parentId === parentId) .map((node) => ({ ...node, children: arrayToTreeRec(nodes, node.id) })); } const tree = arrayToTreeRec(nodes, null);
時(shí)間復(fù)雜度:O(n^2),其中 n 是節(jié)點(diǎn)的數(shù)量。 空間復(fù)雜度:O(n^2)。 優(yōu)缺點(diǎn):不適合大規(guī)模數(shù)據(jù)。
方法二:使用循環(huán)
function arrayToTreeLoop(nodes) { const map = {}; const tree = []; for (const node of nodes) { map[node.id] = { ...node, children: [] }; } for (const node of Object.values(map)) { if (node.parentId === null) { tree.push(node); } else { map[node.parentId].children.push(node); } } return tree; } const tree = arrayToTreeLoop(nodes);
時(shí)間復(fù)雜度:O(n),其中 n 是節(jié)點(diǎn)的數(shù)量。 空間復(fù)雜度:O(n)。 優(yōu)缺點(diǎn):適合大規(guī)模數(shù)據(jù)。
方法三:使用 reduce
function arrayToTreeReduce(nodes) { const map = {}; const tree = nodes.reduce((acc, node) => { map[node.id] = { ...node, children: [] }; if (node.parentId === null) { acc.push(map[node.id]); } else { map[node.parentId].children.push(map[node.id]); } return acc; }, []); return tree; } const tree = arrayToTreeReduce(nodes);
時(shí)間復(fù)雜度:O(n),其中 n 是節(jié)點(diǎn)的數(shù)量。 空間復(fù)雜度:O(n)。 優(yōu)缺點(diǎn):代碼簡(jiǎn)潔,適合中小規(guī)模數(shù)據(jù)。
方法四:使用哈希表
function arrayToTreeMap(nodes) { const map = new Map(nodes.map((node) => [node.id, { ...node, children: [] }])); const tree = []; for (const node of map.values()) { if (node.parentId === null) { tree.push(node); } else { map.get(node.parentId).children.push(node); } } return tree; } const tree = arrayToTreeMap(nodes);
時(shí)間復(fù)雜度:O(n),其中 n 是節(jié)點(diǎn)的數(shù)量。 空間復(fù)雜度:O(n)。 優(yōu)缺點(diǎn):適合大規(guī)模數(shù)據(jù),而且由于使用了 Map
,相比于方法二和方法三,能夠更方便地進(jìn)行節(jié)點(diǎn)的查找和刪除。
方法五:使用深度優(yōu)先搜索
function arrayToTreeDFS(nodes) { const map = new Map(nodes.map((node) => [node.id, { ...node, children: [] }])); const tree = []; for (const node of map.values()) { if (node.parentId === null) { dfs(node, tree); } } function dfs(node, parent) { if (parent) { parent.children.push(node); } for (const child of node.children) { dfs(map.get(child.id), node); } } return tree; } const tree = arrayToTreeDFS(nodes);
時(shí)間復(fù)雜度:O(n),其中 n 是節(jié)點(diǎn)的數(shù)量。 空間復(fù)雜度:O(n)。 優(yōu)缺點(diǎn):相比于方法二、方法三和方法四,可以更方便地進(jìn)行深度優(yōu)先搜索。
總結(jié)
以上是五種常用的將數(shù)組轉(zhuǎn)換為樹(shù)結(jié)構(gòu)的方法,每種方法都有其適用的場(chǎng)景和優(yōu)劣。如果是大規(guī)模數(shù)據(jù),使用方法二或方法四比較合適;如果是中小規(guī)模數(shù)據(jù),使用方法三比較簡(jiǎn)潔;如果需要深度優(yōu)先搜索,可以使用方法五??偟膩?lái)說(shuō),我們需要根據(jù)具體場(chǎng)景選擇最適合的方法來(lái)進(jìn)行數(shù)組到樹(shù)結(jié)構(gòu)的轉(zhuǎn)換。
到此這篇關(guān)于JavaScript實(shí)現(xiàn)樹(shù)結(jié)構(gòu)轉(zhuǎn)換的五種方法總結(jié)的文章就介紹到這了,更多相關(guān)JavaScript樹(shù)結(jié)構(gòu)轉(zhuǎn)換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
ant-design-pro使用qiankun微服務(wù)配置動(dòng)態(tài)主題色的問(wèn)題
這篇文章主要介紹了ant-design-pro使用qiankun微服務(wù)配置動(dòng)態(tài)主題色,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03javascript檢測(cè)瀏覽器flash版本的實(shí)現(xiàn)代碼
javascript檢測(cè)瀏覽器flash版本的實(shí)現(xiàn)代碼,需要的朋友可以參考下。2011-12-12JavaScript 通過(guò)Ajax 動(dòng)態(tài)加載CheckBox復(fù)選框
本文通過(guò)實(shí)例代碼給大家介紹了JavaScript 通過(guò)Ajax 動(dòng)態(tài)加載CheckBox復(fù)選框的方法,需要的朋友參考下吧2017-08-08JS腳本實(shí)現(xiàn)定時(shí)到網(wǎng)站上簽到/簽退功能
這篇文章主要介紹了JS腳本實(shí)現(xiàn)定時(shí)到網(wǎng)站上簽到/簽退功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04JavaScript實(shí)現(xiàn)簡(jiǎn)易放大鏡最全代碼解析(ES5)
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)簡(jiǎn)易放大鏡最全代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09js 客戶(hù)端打印html 并且去掉頁(yè)眉、頁(yè)腳的實(shí)例
下面小編就為大家?guī)?lái)一篇js 客戶(hù)端打印html 并且去掉頁(yè)眉、頁(yè)腳的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11javascript設(shè)計(jì)模式 – 觀察者模式原理與用法實(shí)例分析
這篇文章主要介紹了javascript設(shè)計(jì)模式 – 觀察者模式,結(jié)合實(shí)例形式分析了javascript觀察者模式相關(guān)概念、原理、用法及操作注意事項(xiàng),需要的朋友可以參考下2020-04-04