定义
二叉树是每个节点最多有两个子数的树结构
var tree = {
node: 6,
left: {
node: 5,
left: {
node: 4,
}
right: {
node: 3
}
},
right: {
node: 2,
right: {
node: 1,
}
}
}
二叉树的高度
一般用O(h)来表示更合适,h表示树的层级
二叉树的分类
满二叉树
深度为h,有2^h-1个节点的二叉树
完全二叉树
在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2^h-1个节点。
二叉搜索树
二叉搜索树是一个有序树
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 它的左、右子树也分别为二叉排序树
平衡二叉搜索树
平衡二叉搜索树:又被称为AVL(Adelson-Velsky and Landis)树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
用数组表示二叉树
如果父节点的数组下表是i,那么它的左孩子就是i * 2 + 1,右孩子就是 i * 2 + 2。
分治法
将大规模问题拆分为若干小规模的同类型问题去处理的算法思想; 把一个复杂的问题分成两个或者更多的相同或相似的子问题,再把子问题分成更小的子问题......直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。
什么样的数据结构适合分治法?
二叉树:整颗树的左子树和右子树都是二叉树,二叉树的大部分题都可以使用分治法解决
二叉树深度遍历的三种方式
非递归方式实现前中后序遍历;
function traversal(root, type) {
if (!root) return [];
const order = {
pre: ["val", "left", "right"],
in: ["left", "val", "right"],
post: ["left", "right", "val"],
};
const result = [];
const stack = [root];
while (stack.length) {
const item = stack.pop();
if (typeof item == "number") {
result.push(item);
} else {
const itemArr = order[type];
for (let i = itemArr.length; i >=0; i--) {
const key = itemArr[i];
if (item[key]) {
stack.push(item[key]);
}
}
}
}
return result;
}
- 前序遍历(递归) 根节点-左子树-右子树
var result = []
var dfs = function(nodes) {
if(nodes.node) {
result.push(nodes.node)
nodes.left && dfs(nodes.left)
nodes.right && dfs(nodes.right)
}
}
dfs(nodes)
- 中序遍历 左子树-根节点-右子树
var result = []
var dfs = function(nodes) {
if(nodes.node) {
nodes.left && dfs(nodes.left)
result.push(nodes.node)
nodes.right && dfs(nodes.right)
}
}
dfs(nodes)
- 后序遍历 左子树-右子树-根节点
var result = []
var dfs = function(nodes) {
if(nodes.node) {
nodes.left && dfs(nodes.left)
nodes.right && dfs(nodes.right)
result.push(nodes.node)
}
}
dfs(nodes)
前序、中序、后序指根节点被遍历的顺序;
二叉树广度优先遍历
优点:不会打乱数据结构
递归实现
var result = []
var queue = [nodes]
var bfs3 = function(count) {
count = count || 0
if(queue[count]) {
result.push(queue[count].node)
var left = queue[count].left
var right = queue[count].right
if(left) {
queue.push(left)
}
if(right) {
queue.push(right)
}
bfs3(++count)
}
}
dfs3()
非递归实现
var bfs4 = function(nodes) {
var result = []
var queue = []
var pointer = 0
queue.push(nodes)
while(pointer < queue.length) {
var item = queue[pointer++] // 这里不使用 shift 方法(复杂度高),用一个指针代替
result.push(item.node)
//console.log(item.node)
item.left && queue.push(item.left)
item.right && queue.push(item.right)
}
return result
}
console.log(bfs4(nodes))
总结:大部分考题都是深度遍历相关的,所以学好深度遍历是关键。
写在最后
- 文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎
点赞和关注