一、树是什么?
在计算机领域,树是一种分层数据的抽象模型。在前端工作中常见的树包括:DOM树、级联选择、树形控件……。在JS中没有树,但是可以用 Object 和 Array 构建树。示例如下:
{value: 'zhejiang',label: 'ZheJiang',children: [{value: 'hangzhou',label: 'HangZhou',children: [{value: 'xihu',label: 'West Lake'}}]}
树的常用操作:深度/广度优先遍历、先中后序遍历,这几种遍历非常重要!!!
二、深度与广度优先遍历
深度优先遍历(dfs)
深度优先遍历是尽可能深的搜索树的分支。
如图所示,展示了一个树该如何进行深度优先遍历,其中数字代表访问节点的顺序。
广度优先遍历(bfs)
广度优先遍历是先访问离根节点最近的节点。
如图所示,a 是根节点,先访问离根节点最近的 b 和 c。
以看书为例,将 a 节点想象成一本书的书名,b、c节点想象成一本书的目录,d、e则是每章的页面,深度优先遍历则是我们一页一页翻看这本书。而广度优先遍历则是先看标题,再看目录,再看每章页面。
三、技术实现
深度优先遍历算法口诀
- 访问根节点;
- 对根节点的 children 挨个进行深度优先遍历;
- 对第一步和第二步不断进行重复(递归);
示例
const tree = {val: 'a',children: [{val: 'b',children: [{val: 'd',children: []},{val: 'e',children: []},]},{val: 'c',children: [{val: 'f',children: []},{val: 'g',children: []},]}]}const dfs = (root) => {console.log(root.val) // 第一步:访问根节点root.children.forEach(dfs) // 第二部:对节点进行依次遍历}dfs(tree)
总结下来深度优先遍历就是一个递归。
广度优先遍历算法口诀
- 新建一个队列,把根节点入队;
- 把队头出队并访问;
- 把队头的children挨个入队;
- 重复第二、三步,直到队列为空;
示例
const tree = {val: 'a',children: [{val: 'b',children: [{val: 'd',children: []},{val: 'e',children: []},]},{val: 'c',children: [{val: 'f',children: []},{val: 'g',children: []},]}]}const bfs = (root) => {const queue = [root] // 第一步:新建队列,根节点入队while (queue.length > 0) {const current = queue.shift() // 第二步:队头出队console.log(current.val)current.children.forEach(child => queue.push(child)) // 第三步:队头的 children 入队}}bfs(tree)
