在前端开发中,经常需要对树形数据结构进行遍历处理。tree-crawl
是一个轻量级的 npm 包,可以帮助我们简化树形结构的遍历操作。本文将介绍 tree-crawl
的使用方法,并提供实际案例进行说明。
安装
安装 tree-crawl
非常简单,只需运行以下命令即可:
npm install tree-crawl
使用方法
构建树形数据结构
首先我们需要准备一份树形数据结构。在本文中,我们将以以下 JSON 数据为例:
-- -------------------- ---- ------- - ----- -- -------- ------- ----------- - - ----- -- -------- ------ --- ----------- - - ----- -- -------- ------ ----- ----------- -- -- - ----- -- -------- ------ ----- ----------- - - ----- -- -------- ------ ------- ----------- -- - - - - -- - ----- -- -------- ------ --- ----------- -- - - -
导入 tree-crawl
在项目中导入 tree-crawl
:
const TreeCrawl = require('tree-crawl');
初始化 TreeCrawl 对象
接下来我们需要初始化 TreeCrawl
对象。TreeCrawl
构造函数需要接受一个参数,即树形数据结构。在本文中,我们将以上述 JSON 数据为参数初始化 TreeCrawl
对象:
-- -------------------- ---- ------- ----- -------- - - ----- -- -------- ------- ----------- - - ----- -- -------- ------ --- ----------- - - ----- -- -------- ------ ----- ----------- -- -- - ----- -- -------- ------ ----- ----------- - - ----- -- -------- ------ ------- ----------- -- - - - - -- - ----- -- -------- ------ --- ----------- -- - - -- ----- --------- - --- --------------------
遍历树形结构
现在我们可以使用 TreeCrawl
提供的方法遍历树形结构了。TreeCrawl
提供了以下方法:
depthFirstSearch
: 深度优先搜索breadthFirstSearch
: 广度优先搜索preorderTraversal
: 前序遍历inorderTraversal
: 中序遍历postorderTraversal
: 后序遍历
以 depthFirstSearch
方法为例,我们可以按照以下方式进行遍历:
treeCrawl.depthFirstSearch((node, level, path) => { console.log('Node:', node); console.log('Level:', level); console.log('Path:', path); });
depthFirstSearch
方法接受一个回调函数作为参数,该回调函数会在遍历到每个节点时被调用。回调函数接收三个参数:
node
: 当前遍历到的节点level
: 当前节点所在的深度path
: 从根节点到当前节点的路径
在上述示例中,回调函数会输出每个遍历到的节点、该节点所在深度,以及该节点从根节点到达的路径。
遍历结果解释
以本文中的树形结构为例,使用 depthFirstSearch
方法进行遍历的结果如下:
-- -------------------- ---- ------- ----- - --- -- ------ ------- --------- - - --- -- ------ ------ --- --------- ------- -- - --- -- ------ ------ --- --------- -- - - - ------ - ----- - - --- -- ------ ------- --------- ------- - - ----- - --- -- ------ ------ --- --------- - - --- -- ------ ------ ----- --------- -- -- - --- -- ------ ------ ----- --------- ------- - - - ------ - ----- - - --- -- ------ ------- --------- ------- -- - --- -- ------ ------ --- --------- ------- - - ----- - --- -- ------ ------ ----- --------- -- - ------ - ----- - - --- -- ------ ------- --------- ------- -- - --- -- ------ ------ --- --------- ------- -- - --- -- ------ ------ ----- --------- -- - - ----- - --- -- ------ ------ ----- --------- - - --- -- ------ ------ ------- --------- -- - - - ------ - ----- - - --- -- ------ ------- --------- ------- -- - --- -- ------ ------ --- --------- ------- -- - --- -- ------ ------ ----- --------- ------- - - ----- - --- -- ------ ------ ------- --------- -- - ------ - ----- - - --- -- ------ ------- --------- ------- -- - --- -- ------ ------ --- --------- ------- -- - --- -- ------ ------ ----- --------- ------- -- - --- -- ------ ------ ------- --------- -- - - ----- - --- -- ------ ------ --- --------- -- - ------ - ----- - - --- -- ------ ------- --------- ------- -- - --- -- ------ ------ --- --------- -- - -
解释一下上述遍历结果:
- 遍历过程中先访问根节点
Root
,它深度为0
,路径为[{ id: 1, label: 'Root', children: [Array] }]
; - 接下来遍历根节点的所有子节点,先遍历
Child 1
节点,它深度为1
,路径为[{ id: 1, label: 'Root', children: [Array] }, { id: 2, label: 'Child 1', children: [Array] }]
; - 继续遍历
Child 1
的所有子节点,先遍历Child 1.1
节点,它深度为2
,路径为[{ id: 1, label: 'Root', children: [Array] }, { id: 2, label: 'Child 1', children: [Array] }, { id: 3, label: 'Child 1.1', children: [] }]
;注意此时路径中最后一个节点是叶子节点。 - 接下来遍历
Child 1.2
节点,它深度为2
,路径为[{ id: 1, label: 'Root', children: [Array] }, { id: 2, label: 'Child 1', children: [Array] }, { id: 4, label: 'Child 1.2', children: [Array] }]
;该节点有子节点,继续遍历其子节点。 - 遍历
Child 1.2
的子节点Child 1.2.1
,深度为3
,路径为[{ id: 1, label: 'Root', children: [Array] }, { id: 2, label: 'Child 1', children: [Array] }, { id: 4, label: 'Child 1.2', children: [Array] }, { id: 5, label: 'Child 1.2.1', children: [] }]
;该节点是叶子节点,遍历完毕。 - 接下来遍历根节点的另一个子节点
Child 2
,深度为1
,路径为[{ id: 1, label: 'Root', children: [Array] }, { id: 6, label: 'Child 2', children: [] }]
;它是叶子节点,遍历过程结束。
方法说明与案例
上述方法有不同之处,接下来我们依次进行介绍并提供实际案例。
depthFirstSearch
该方法采用深度优先遍历,即首先访问完整条路径的最深端节点,然后回溯到前一级节点并访问其他子节点。
treeCrawl.depthFirstSearch((node, level, path) => { console.log('Node:', node); console.log('Level:', level); console.log('Path:', path); });
示例输出结果看上去和上面的结果相似,但遍历方式不同。console:
-- -------------------- ---- ------- ----- - --- -- ------ ------- --------- - - --- -- ------ ------ --- --------- ------- -- - --- -- ------ ------ --- --------- -- - - - ------ - ----- - - --- -- ------ ------- --------- ------- - - ----- - --- -- ------ ------ --- --------- - - --- -- ------ ------ ----- --------- -- -- - --- -- ------ ------ ----- --------- ------- - - - ------ - ----- - - --- -- ------ ------- --------- ------- -- - --- -- ------ ------ --- --------- ------- - - ----- - --- -- ------ ------ ----- --------- -- - ------ - ----- - - --- -- ------ ------- --------- ------- -- - --- -- ------ ------ --- --------- ------- -- - --- -- ------ ------ ----- --------- -- - - ----- - --- -- ------ ------ ----- --------- - - --- -- ------ ------ ------- --------- -- - - - ------ - ----- - - --- -- ------ ------- --------- ------- -- - --- -- ------ ------ --- --------- ------- -- - --- -- ------ ------ ----- --------- ------- - - ----- - --- -- ------ ------ ------- --------- -- - ------ - ----- - - --- -- ------ ------- --------- ------- -- - --- -- ------ ------ --- --------- ------- -- - --- -- ------ ------ ----- --------- ------- -- - --- -- ------ ------ ------- --------- -- - - ----- - --- -- ------ ------ --- --------- -- - ------ - ----- - - --- -- ------ ------- --------- ------- -- - --- -- ------ ------ --- --------- -- - -
breadthFirstSearch
该方法采用广度优先遍历,即按照节点深度顺序分层访问。
treeCrawl.breadthFirstSearch((node, level, path) => { console.log('Node:', node); console.log('Level:', level); console.log('Path:', path); });
结果中节点的顺序和 depthFirstSearch 不同,是先层级遍历。
console:
-- -------------------- ---- ------- ----- - --- -- ------ ------- --------- - - --- -- ------ ------ --- --------- ------- -- - --- -- ------ ------ --- --------- -- - - - ------ - ----- - - --- -- ------ ------- --------- ------- - - ----- - --- -- ------ ------ --- --------- - - --- -- ------ ------ ----- --------- -- -- - --- -- ------ ------ ----- --------- ------- - - - ------ - ----- - - --- -- ------ ------- --------- ------- -- - --- -- ------ ------ --- --------- ------- - - ----- - --- -- ------ ------ --- --------- -- - ------ - ----- - - --- -- ------ ------- --------- ------- -- - --- -- ------ ------ --- --------- -- - - ----- - --- -- ------ ------ ----- --------- -- - ------ - ----- - - --- -- ------ ------- --------- ------- -- - --- -- ------ ------ --- --------- ------- -- - --- -- ------ ------ ----- --------- -- - - ----- - --- -- ------ ------ ----- --------- - - --- -- ------ ------ ------- --------- -- - - - ------ - ----- - - --- -- ------ ------- --------- ------- -- - --- -- ------ ------ --- --------- ------- -- - --- -- ------ ------ ----- --------- ------- - - ----- - --- -- ------ ------ ------- --------- -- - ------ - ----- - - --- -- ------ ------- --------- ------- -- - --- -- ------ ------ --- --------- ------- -- - --- -- ------ ------ ----- --------- ------- -- - --- -- ------ ------ ------- --------- -- - -
preorderTraversal
前序遍历指的是先访问父节点,然后依次访问左右子节点。
treeCrawl.preorderTraversal((node, level, path) => { console.log('Node:', node); console.log('Level:', level); console.log('Path:', path); });
console:
-- -------------------- ---- ------- ----- - --- -- ------ ------- --------- - - --- -- ------ ------ --- --------- ------- -- - --- -- ------ ------ --- --------- -- - - - ------ - ----- - - --- -- ------ ------- --------- ------- - - ----- - --- -- ------ ------ --- --------- - - --- -- ------ ------ ----- --------- -- -- - --- -- ------ ------ ----- --------- ------- - - - ------ - ----- - - --- -- ------ ------- --------- ------- -- - --- -- ------ ------ --- --------- ------- - - ----- - --- -- ------ ------ ----- --------- -- - ------ - ----- - - --- -- ------ ------- --------- ------- -- - --- -- ------ ------ --- --------- ------- -- - --- -- ------ ------ ----- --------- -- - - ----- - --- -- ------ ------ ----- --------- - - --- -- ------ ------ ------- --------- -- - - - ------ - ----- - - --- -- ------ ------- --------- ------- -- - --- -- ------ ------ --- --------- ------- -- - --- -- ------ ------ ----- --------- ------- - - ----- - --- -- ------ ------ ------- --------- -- - ------ - ----- - - --- -- ------ ------- --------- ------- -- - --- -- ------ ------ --- --------- ------- -- - - ------------------------------------------------------------------------------ -------- ------------------------------------------------------------------------------------------------------------------------