一、二叉树基础理论篇
满二叉树和完全二叉树:只是差在最后一层是否被填满
二叉搜索树:
若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
它的左、右子树也分别为二叉排序树
平衡二叉搜索树:又被称为AVL(Adelson-Velsky and Landis)树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。增删操作时间复杂度为O(logn)。
二叉树的存储方式:一种是左指针右指针的链式存储,另一种是层序遍历节点下标的数组存储。
深度优先遍历当中,前中后序遍历指的就是中间节点的遍历顺序。
链式存储二叉树的定义:
function TreeNode(val, left, right) {
this.val = (val===undefined ? 0 : val)
this.left = (left===undefined ? null : left)
this.right = (right===undefined ? null : right)
}
二、二叉树的递归遍历
递归法思路:js当中需要使用闭包,将递归封装成一个函数影响函数外面的result数组,然后在函数外面将result返回。前中后序就是根节点的遍历顺序。
var preorderTraversal = function(root) {
// 递归法
var result = [];
var dfs = function(root) {
if (!root) {
return;
}
result.push(root.val);
dfs(root.left);
dfs(root.right);
}
dfs(root);
return result;
};
var postorderTraversal = function(root) {
// 递归法
var result = [];
var dfs = function(root) {
if (!root) {
return;
}
dfs(root.left);
dfs(root.right);
result.push(root.val);
}
dfs(root);
return result;
};
var inorderTraversal = function(root) {
var result = [];
var dfs = function(root) {
if (!root) {
return;
}
dfs(root.left);
result.push(root.val);
dfs(root.right);
}
dfs(root);
return result;
};
三、二叉树的迭代遍历
前序迭代法:借助一个栈,每一次从栈中pop出根节点,将val放入结果当中,然后将其右子树和左子树分别放入栈中,依次进行。
代码:
var preorderTraversal = function(root) {
// 迭代法
if (!root) {
return [];
}
var stack = [];
var result = [];
stack.push(root);
while (stack.length !== 0) {
var cur = stack.pop();
result.push(cur.val);
if (cur.right)
stack.push(cur.right);
if (cur.left)
stack.push(cur.left);
}
return result;
};
后序迭代法:和前序类似,但是要改变左右子树进栈的顺序,使出栈顺序变成中右左,然后反转result变成左右中。
代码:
var postorderTraversal = function(root) {
// 迭代法
if (!root) {
return [];
}
var result = [];
var stack = [];
stack.push(root);
while (stack.length) {
var cur = stack.pop();
result.push(cur.val);
//此处让左子树先入栈,使出栈的顺序变成中右左
if (cur.left)
stack.push(cur.left);
if (cur.right)
stack.push(cur.right);
}
// 再返回result数组的反转,使输出变为左右中
return result.reverse();
};
中序迭代法:对于每一个节点,先将它的左子树按深度搜索全部入栈,然后依次出栈,如果没有左子树就将其值加入,然后处理右子树。
代码:
var inorderTraversal = function(root) {
// 迭代法
if (!root) {
return [];
}
var stack = [];
var cur = root;
while (cur || stack.length !== 0) {
if (cur) {
// 左
stack.push(cur);
cur = cur.left;
}
else {
// --> 弹出 中
cur = stack.pop();
res.push(cur.val);
// 右
//如果该节点没有右子树,下一次的循环当中会继续出栈,直到出现有右子树的节点
cur = cur.right;
}
}
return result;
};
今日学习时间:2h左右
总结:今天主要学习了二叉树的递归迭代和遍历迭代,递归较简单,下次再刷的时候需要重点看中序遍历的迭代方法。