满二叉树
二叉树只有枝为0或者为2的节点,并且枝为0的节点在同一层
如图
这种是为满二叉树
这种不是满二叉树
完全二叉树
完全二叉树就是叶节点只能出现在最下层或者次下层,最下面一层的结点都集中在该层最左边的若干位置的二叉树
二叉搜索树
前面介绍的树,都没有数值的,而二叉搜索树是有数值的了,二叉搜索树是一个有序树。
若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
它的左、右子树也分别为二叉排序树
下面这两棵树都是搜索树
平衡二叉搜索树
平衡二叉搜索树:又被称为AVL(Adelson-Velsky and Landis)树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
如图:
最后一棵 不是平衡二叉树,因为它的左右两个子树的高度差的绝对值超过了1。
二叉树遍历方式
二叉树只有两种遍历方式 即 广度优先遍历和深度优先遍历
-
深度优先遍历
-
- 前序遍历(递归法,迭代法)
-
- 中序遍历(递归法,迭代法)
-
- 后序遍历(递归法,迭代法)
-
广度优先遍历
-
- 层次遍历(迭代法)
- 前序遍历:中左右
- 中序遍历:左中右
- 后序遍历:左右中
递归遍历法
前序遍历
就是先push 再递归左右树
var preorderTraversal = function(root) {
let res=[];
const dfs=function(root){
if(root===null)return ;
//先序遍历所以从父节点开始
res.push(root.val);
//递归左子树
dfs(root.left);
//递归右子树
dfs(root.right);
}
//只使用一个参数 使用闭包进行存储结果
dfs(root);
return res;
};
中序遍历
就是先递归左树 再push 再递归右树
var inorderTraversal = function(root) {
let res=[];
const dfs=function(root){
if(root===null){
return ;
}
dfs(root.left);
res.push(root.val);
dfs(root.right);
}
dfs(root);
return res;
};
后序遍历
就是先遍历左树 再遍历右树再push
var inorderTraversal = function(root) {
let res=[];
const dfs=function(root){
if(root===null){
return ;
}
dfs(root.left);
dfs(root.right);
res.push(root.val);
}
dfs(root);
return res;
};
迭代法
前序遍历
前序遍历的迭代法用栈就可以实现,我们先将头节点放入栈中,然后每个节点出栈的时候,先入栈其右子节点,再入栈左子节点就可以了
var preorderTraversal = function(root) {
const res = [];
if (root == null) return res;
const stack = [root];
while(stack.length != 0){
let item = stack.pop();
res.push(item.val);
if(item.right) stack.push(item.right);
if(item.left) stack.push(item.left);
};
return res;
}
中序遍历
其实用一个栈也能做出来,
我们只需要先从头节点开始,把最左边的节点全部压进栈,然后我们每出栈一个节点就去遍历他右节点的左节点,重复上面的操作
const inorderTraversal = (root) => {
const res = [];
const stack = [];
while (root) { // 能压栈的左子节点都压进来
stack.push(root);
root = root.left;
}
while (stack.length) {
let node = stack.pop(); // 栈顶的节点出栈
res.push(node.val); // 在压入右子树之前,处理它的数值部分(因为中序遍历)
node = node.right; // 获取它的右子树
while (node) { // 右子树存在,执行while循环
stack.push(node); // 压入当前root
node = node.left; // 不断压入左子节点
}
}
return res;
}
后续遍历
再来看后序遍历,先序遍历是中左右,后续遍历是左右中,那么我们只需要调整一下先序遍历的代码顺序,就变成中右左的遍历顺序,然后在反转result数组,输出的结果顺序就是左右中了,如下图:
var inorderTraversal = function(root) {
const res = [];
if (root == null) return res;
const stack = [root];
while(stack.length != 0){
let item = stack.pop();
res.push(item.val);
if(item.left) stack.push(item.left);
if(item.right) stack.push(item.right);
};
return res.reverse();
};
};