数据结构之“树”

  • 树是什么?
  • 什么是深度/广度优先遍历?
  • 深度优先遍历算法口诀
  • 广度优先遍历算法口诀
  • 二叉树的先中后序遍历
    • 二叉树是什么
    • 先序遍历算法口诀(根 > 左 > 右)
    • 中序遍历算法口诀(左 > 根 > 右)
    • 后序遍历算法口诀(左 > 右 > 根)
  • LeetCode:104.二叉树的最大深度
  • LeetCode:111.二叉树的最小深度
  • LeetCode:102.二叉树的层序遍历
  • LeetCode:94.二叉树的中序遍历
  • LeetCode:112.路径总和
  • 前端与树:遍历JSON的所有节点值
  • 前端与树:渲染Antd中的树组件
  • 技术要点
  • 思考题

树是什么?

  • 一种分层数据的抽象模型。
  • 前端工作中常见的树包括:DOM树、级联选择、树形控件…

  • JS中没有树,但是可以用Object和Array构建树

  • 树的常用操作:深度/广度优先遍历、先中后序遍历

什么是深度/广度优先遍历?

  • 深度优先遍历,尽可能深的搜索树的分支

  • 广度优先遍历:先访问离根节点最近的节点

深度优先遍历算法口诀

  • 访问根节点
  • 对根节点的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 q = [root];while (q.length > 0) {const n = q.shift();console.log(n.val);n.children.forEach(child => {q.push(child);});}
};bfs(tree);

二叉树的先中后序遍历

二叉树是什么

  • 树中每个节点最多只能有两个子节点
  • 在JS中通常用Object来模拟二叉树


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,},},
};module.exports = bt;

先序遍历算法口诀(根 > 左 > 右)

  • 访问根节点
  • 对根节点的左子树进行先序遍历
  • 对根节点的右子树进行先序遍历
const bt = require('./bt');const preorder = (root) => {if (!root) { return; }console.log(root.val);preorder(root.left);preorder(root.right);
};// 非递归版
// const preorder = (root) => {//     if (!root) { return; }
//     const stack = [root];
//     while (stack.length) {//         const n = stack.pop();
//         console.log(n.val);
//         if (n.right) stack.push(n.right);
//         if (n.left) stack.push(n.left);
//     }
// };preorder(bt);

中序遍历算法口诀(左 > 根 > 右)

  • 对根节点的左子树进行中序遍历
  • 访问根节点
  • 对根节点的右子树进行中序遍历

const bt = require('./bt');const inorder = (root) => {if (!root) { return; }inorder(root.left);console.log(root.val);inorder(root.right);
};// 非递归版
// const inorder = (root) => {//     if (!root) { return; }
//     const stack = [];
//     let p = root;
//     while (stack.length || p) {//         while (p) {//             stack.push(p);
//             p = p.left;
//         }
//         const n = stack.pop();
//         console.log(n.val);
//         p = n.right;
//     }
// };inorder(bt);

后序遍历算法口诀(左 > 右 > 根)

  • 对根节点的左子树进行后序遍历
  • 对根节点的右子树进行后序遍历
  • 访问根节点

const bt = require('./bt');const postorder = (root) => {if (!root) { return; }postorder(root.left);postorder(root.right);console.log(root.val);
};// 非递归版,做法:类似先序遍历倒过来
// const postorder = (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);
//     }
// };postorder(bt);

LeetCode:104.二叉树的最大深度

使用深度优先遍历解决

解题思路
求最大深度,考虑使用深度优先遍历
在深度优先遍历过程中,记录每个节点所在的层级,找出最大的层级即可
解题步骤
新建一个变量,记录最大深度
深度优先遍历整棵树,并记录每个节点的层级,同时不断刷新最大深度这个变量
遍历结束返回最大深度这个变量

时间复杂度O(n),n是整棵树的节点数
有函数调用堆栈,函数没有执行完变量不能释放,所以空间复杂度为O(最大深度),好的情况是每个都有两个叉,空间复杂度为O(log(n)),最坏的情况是节点数等于最大深度,只在一个叉上不断延续的二叉树,空间复杂度为O(n)

LeetCode:111.二叉树的最小深度

使用广度优先遍历解决

解题思路
求最小深度,考虑使用广度优先遍历
在广度优先遍历过程中,遇到叶子节点,停止遍历,返回节点层级
解题步骤
广度优先遍历整棵树,并记录每个节点的层级
遇到叶子节点,返回节点层级,停止遍历

时间复杂度O(n),n是整棵树的节点数
空间复杂度为O(n)

LeetCode:102.二叉树的层序遍历


解题思路
层序遍历顺序就是广度优先遍历
不过在遍历时候需要记录当前节点所处的层级,方便将其添加到不同的数组中
解题步骤
广度优先遍历二叉树
遍历过程中,记录每个节点的层级,并将其添加到不同的数组中

  • 法一

  • 法二

    时间复杂度O(n),空间复杂度为O(n)

LeetCode:94.二叉树的中序遍历


递归版

非递归版

时间复杂度O(n),空间复杂度为O(n)

LeetCode:112.路径总和


解题思路
在深度优先遍历的过程中,记录当前路径的节点值的和
在叶子节点处,判断当前路径的节点值的和是否等于目标值
解题步骤
深度优先遍历二叉树,在叶子节点处,判断当前路径的节点值的和是否等于目标值,是就返回true
遍历结束,如果没有匹配,就返回false

时间复杂度O(n),n为树的节点数,空间复杂度为O(树的高度),最坏为O(n),最好为O(log(n))

前端与树:遍历JSON的所有节点值

const json = {a: { b: { c: 1 } },d: [1, 2],
};const dfs = (n, path) => {console.log(n, path);Object.keys(n).forEach(k => {dfs(n[k], path.concat(k));});
};dfs(json, []);

前端与树:渲染Antd中的树组件

技术要点

树是一种分层数据的抽象模型,在前端广泛应用
树的常用操作:深度/广度优先遍历、先中后序遍历…

思考题

1、用React或Vue编写一个省市区级联选择
2、用React或Vue编写一个树插件,要求可以将json渲染到页面上即可

(八)数据结构之“树”相关推荐

  1. 数据结构显示树的所有结点_您需要了解的有关树数据结构的所有信息

    数据结构显示树的所有结点 When you first learn to code, it's common to learn arrays as the "main data struct ...

  2. 数据结构树的基本操作_《数据结构》树的基本操作.doc

    <数据结构>树的基本操作 实验四 课程名称:完成日期:姓名:学号:指导教师:实验名称:实验序号:实验成绩:一.实验目的及要求 二.实验环境.实验内容 求出它的深度. .调试过程及实验结果 ...

  3. 数据结构-王道-树和二叉树

    [top] 树和二叉树 树:是\(N(N\geq0)\)个结点的有限集合,\(N=0\)时,称为空树,这是一种特殊情况.在任意一棵非空树中应满足: 有且仅有一个特定的称为根的结点. 当\(N>1 ...

  4. 数据结构之树:树的介绍——9

    数据结构之树,介绍篇 树的基本定义 介绍:树(tree)是计算机中非常重要的数据结构,它的外形看起来像一颗倒挂着的的树,使用树这种结构可以描述生活中很多的事物,如族谱,单位的组织架构,xml,html ...

  5. 数据结构之树的存储结构

    数据结构之树的存储结构 思维导图 双亲表示法: 增 删 孩子表示法: 孩子兄弟表示法:(重要) 森林和二叉树的转化 思维导图 双亲表示法: 增 增加M.L节点 删 删除G节点(叶节点) 删除(非叶节点 ...

  6. Linux 内核里的数据结构——基数树

    Linux 内核里的数据结构--基数树 正如你所知道的,Linux内核提供了许多不同的库和函数,它们实现了不同的数据结构和算法.在这部分,我们将研究其中一种数据结构--基数树Radix tree.在 ...

  7. 【数据结构】 树与二叉树的基本概念、结构特点及性质

    前言:本章内容主要是数据结构中树与二叉树的基本概念.结构特点及性质的引入. 文章目录 树的概念 树的特点: 树的常用术语: 树的表示: 代码创建: 树在实际中的应用: 二叉树的概念 特殊的二叉树 满二 ...

  8. 【技术点】数据结构--B树系列之B+树(五)

    文章目录 前言 B+树的结构 Key & Data 叶子节点保存数据:减少I/O的设计 中间节点的索引作用 链表的作用:范围查询 B+树的操作 插入 删除 B+树总结 B*树 总结 前言 前面 ...

  9. 数据结构之树与二叉树

    数据结构之树与二叉树 1.树的概念及结构 1.1.什么是树? 树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合.树是递归定义的.之所以把它叫做树是因为它看起来像 ...

最新文章

  1. 图像HSV和RGB的相互转换
  2. bert pytorch源码_【PyTorch】梯度爆炸、loss在反向传播变为nan
  3. python在日常工作处理中的应用-Python在工作中的应用
  4. python性能优化之函数执行时间分析_python性能优化之函数执行时间分析
  5. sink xxx does not exist
  6. C++笔记——指向常量的指针/指针常量
  7. SpringCloud注解和配置以及pom依赖说明
  8. TortoiseGit功能介绍
  9. SQL Server2008函数大全(完整版)
  10. visio一分二的箭头_Microsoft Office Visio绘画双箭头直线的具体步骤介绍
  11. 类iGoogle实现参考资料
  12. 企业文化五因素论(转载)
  13. 谢菲尔德大学计算机科学学院地理位置,2020年谢菲尔德大学在哪里及校区详细地址介绍...
  14. 洛谷——P1361 小猫爬山
  15. 51nod3146 绿豆蛙的归宿
  16. 科视激光投影和多媒体系统在上海天文馆与你相约浩瀚宇宙
  17. C语言程序设计第五章循环结构程序设计总结
  18. Android 5.0、6.0、7.0、8.0主要新特性
  19. 以太网卡TSO、GSO、LRO、GRO描述及相关配置
  20. ADC采集电路前级为啥加一个电压跟随器?

热门文章

  1. spark之3:安装部署
  2. win10安装docker
  3. linux中的du 命令详解
  4. python科学计算笔记(四)pandas 数据索引与选取
  5. Spark RDD的缓存
  6. 如何将不同类型数据导入Elaticsearch中?
  7. Android 实现九宫格、点击图片放大全屏浏览等
  8. 《HTML、CSS、JavaScript 网页制作从入门到精通》——第6章 使用表格
  9. 图像处理之基础---傅里叶
  10. 写MySQL存储过程实现动态执行SQL