树是什么?

  • 树是一种分层数据的抽象模型
  • 前端工作中常见的树包括:DOM 树、级联选择、树型控件(目录树)

树的实现

  • JS 中没有树这个数据结构,使用 Object 和 Array 来构建树
    1. {
    2. value: 'zhejiang',
    3. label: 'zhejiang',
    4. children: [
    5. {
    6. value: 'hangzhou',
    7. label: 'Hangzhou',
    8. children: [
    9. {
    10. value: 'xihu',
    11. label: 'Xihu'
    12. }
    13. ]
    14. }
    15. ],
    16. }

树的常用操作

深度优先遍历(DFS)

  • 尽可能深的搜索树的分支(数字代表访问的顺序)

树 - 图1

  • 算法口诀
    1. 访问根节点
    2. 对根节点的 children 挨个进行深度优先遍历
  • 代码实现 ```javascript const root = { val: ‘a’, children: [
    1. {
    2. val: 'b',
    3. children: [
    4. {
    5. val: 'd',
    6. children: [],
    7. },
    8. {
    9. val: 'e',
    10. children: [],
    11. }
    12. ],
    13. },
    14. {
    15. val: 'c',
    16. children: [
    17. {
    18. val: 'f',
    19. children: [],
    20. },
    21. {
    22. val: 'g',
    23. children: [],
    24. }
    25. ],
    26. }
    ], }

getResult(root) { // 1.定义结果数组 let result = []; // 2.定义递归函数 const dfs = (root) => { // 访问根节点 console.log(root.val); result.push(root.val); // 对根节点的 children 挨个进行深度优先遍历 root.children.forEach(element => { dfs(element); }); // 可缩写为 root.children.forEach(dfs) } // 3.调用递归函数 dfs(root); // 4.返回结果 return result; }

  1. <a name="TYOjl"></a>
  2. #### 广度优先遍历
  3. - 先访问离根节点最近的节点
  4. ![](https://cdn.nlark.com/yuque/0/2022/jpeg/136255/1650223556294-2af80242-bc14-4fdf-932e-2bca7a424107.jpeg)
  5. - 算法口诀
  6. - ① 新建一个队列,把根节点入队
  7. - ② 把队头出队并访问
  8. - ③ 把队头的 children 挨个入队
  9. - ④ 重复 ②、③ 步,直到队列为空
  10. - 代码实现
  11. ```javascript
  12. const root = {
  13. val: 'a',
  14. children: [
  15. {
  16. val: 'b',
  17. children: [
  18. {
  19. val: 'd',
  20. children: [],
  21. },
  22. {
  23. val: 'e',
  24. children: [],
  25. }
  26. ],
  27. },
  28. {
  29. val: 'c',
  30. children: [
  31. {
  32. val: 'f',
  33. children: [],
  34. },
  35. {
  36. val: 'g',
  37. children: [],
  38. }
  39. ],
  40. }
  41. ],
  42. }
  43. getResult(root) {
  44. // 1.定义结果数组
  45. let result = [];
  46. // 2.定义递归函数
  47. const bfs = (root) => {
  48. // 新建一个队列,把根节点放入
  49. let q = [root];
  50. // 循环执行
  51. while(q.length > 0) {
  52. // 队列头节点出队
  53. let n = q.shift();
  54. // 访问头节点
  55. console.log(n.val);
  56. result.push(n.val);
  57. n.children.forEach(child => {
  58. q.push(child);
  59. })
  60. }
  61. }
  62. // 3.调用递归函数
  63. bfs(root);
  64. // 4.返回结果
  65. return result;
  66. }

二叉树特有 - 先中后序遍历

二叉树的先序遍历(深度优先遍历),注意 JS 闭包的使用

  1. var preorderTraversal = function (root) {
  2. // 首先声明一个数组用来存放遍历得到的节点val值
  3. const result = []
  4. // 定义递归函数
  5. function preorder(node) {
  6. // 如果节点为空直接返回
  7. if (!node) return
  8. // 先序遍历就是把当前节点输出 放在左右递归调用之前 将其数值放入结果数组
  9. result.push(node.val)
  10. // 然后递归遍历左孩子
  11. preorder(node.left)
  12. // 最后递归遍历右孩子
  13. preorder(node.right)
  14. }
  15. preorder(root)
  16. // 返回结果
  17. return result
  18. };