二叉树
每个节点最多有两个子树的树结构,左子树和右子树
二叉树遍历
- 广度优先遍历 使用队列
- 深度优先遍历 使用栈(前序、中序、后序)
广度优先遍历
利用一个数组,先存入根结点,然后依次存入左右节点,每次从头部取出第一个进行操作(越先存入越早取出)
中序遍历
左根右
递归
思路:递归左,根,递归右
非递归(迭代)
思路:
定义一个栈数组,一个结果数组
- 取根结点为目标节点,开始遍历
- 左孩子入栈,直到左孩子为空的节点
- 节点出栈,访问该节点
- 以右孩子为目标节点,依次执行前三项
|
|
前序遍历
根左右
递归
思路:根,递归左,递归右
非递归(迭代)
思路:
定义一个栈数组,一个结果数组
- 取根结点为目标节点,开始遍历
- 访问目标节点
- 左孩子入栈,直到左孩子为空的节点
- 节点出栈,以右孩子为目标节点,依次执行前三项
|
|
后序遍历
左右根
递归
思路:递归左,递归右,根
非递归(迭代)
思路:
定义一个栈数组,一个结果数组
- 取根结点为目标节点,开始遍历
- 用一个标志位last来标记上一个访问的节点
- 左孩子入栈,直到左孩子为空的节点
- 如果栈顶节点的右节点为空或者右节点被访问过=>节点出栈,访问该节点,将节点标记为已访问
- 否则,以右孩子为目标节点,重复以上
|
|
重建二叉树
根据前序遍历pre和中序遍历vin重建二叉树
思路:
- 如果长度是0或者1,直接return null或者return一个节点
- 前序遍历找到根节点root(第一个)
- 找到root在中序中的位置index
- 根据index得到左右子树的前、中遍历
- 递归
|
|
对称二叉树
根节点相同,左右节点交换位置
判断是不是对称二叉树
思路:判断两个节点的关系
- 如果都没有,true
- 如果有一个没有,false
- 如果值不同,false
- 递归:比较节点1的左和节点2的右,比较节点1的右和节点2的左
|
|
求对称二叉树
|
|
二叉搜索树
- 左子树的所有节点都小于根节点的值
- 右子树的所有节点都大于根节点的值
- 左右子树分别为二叉搜索树
判断是不是二叉搜索树
思路:利用二叉搜索树的中序遍历是有序的特点
|
|
判断是不是一个二叉搜索树的后序遍历
思路:后序遍历 = 左子树 + 右子树 + 根
- 先检测左子树,左侧比根节点小的值都被判定为左子树
- 除最后一个节点外和左子树的其他值为右子树,右子树有一个比根节点小,则返回false
- 若存在左、右子树,递归检测左、右子树是否符合规范
|
|
二叉树的深度
深度:根节点到最远叶子节点的最长路径上的节点数
二叉树的最大深度
|
|
二叉树的最小深度
|
|
平衡二叉树
- 每个子树的深度之差不超过1
判断平衡二叉树
思路:
- 后序遍历二叉树,在遍历二叉树每个节点前都会遍历其左右子树
- 比较左右子树的深度,若差值大于1则返回一个标记-1,表示不平衡
- 左右子树有一个不平衡,或左右子树差值大于1,则整棵树不平衡
- 若左右子树平衡,返回当前树的深度123456789101112131415function isBalanced(root){return depth(root)!=-1;}function depth(node){if(!node){return 0;}const left = depth(node.left);const right = depth(node.right);if(left==-1||right==-1||Math.abs(left-right)>1){return -1;}return Math.max(left,right)+1}
二叉树的层平均值
思路:
- 用层序遍历bfs的方法,维护一个队列去遍历节点
- 用for循环控制一层的节点逐个出列,节点值累加求和
- 节点出列的同时,下一层的子节点加入队列,在for循环结束时候,队列中就全是下一层的节点
- 用当前层的求个除以节点个数,加入结果数组
- 接着处理下一层,重复以上步骤
|
|