1.二叉树的构建
// 定义二叉树的节点
function TreeNode(val, left, right) {
this.val = val === undefined ? 0 : val
this.left = left === undefined ? null : left
this.right = right === undefined ? null : right
}
// 定义二叉树的构造函数
function CompleteBinaryTree() { }
// 原型方法1:根据层序遍历构建二叉树
CompleteBinaryTree.prototype.buildTree = function (arr) {
var len = arr.length
if (len === 0) return null
var root = new TreeNode(arr[0]) // 定义根节点
if (len === 1) return root
var queue = [root] // 定义一个队列用于存放需要添加左右节点的子节点
var curRoot = null // 定义当前需要被添加左右子节点的节点
// 遍历queue,得到当前需要被添加左右子节点的节点
for (var i = 0; i < queue.length; i++) {
curRoot = queue[i]
// 1.当前节点有左节点(根据数组长度判断)
if (2 * i + 1 < len) {
// 左节点为空
if (arr[2 * i + 1] === null) {
curRoot.left = null
} else { // 左节点不为空
curRoot.left = new TreeNode(arr[2 * i + 1])
queue.push(curRoot.left) // 将左节点放进队列
}
}
// 2.当前节点有右节点
if (2 * i + 2 < len) {
// 右节点为空
if (arr[2 * i + 2] === null) {
curRoot.right = null
} else { // 右节点不为空
curRoot.right = new TreeNode(arr[2 * i + 2])
queue.push(curRoot.right) // 将右节点放进队列
}
}
}
return root
}
// 输入数据
var arr = [1, null, 2, 3, null, 4, null]
var myTree = new CompleteBinaryTree()
var root = myTree.buildTree(arr)
// console.log(root);
2.广度优先遍历BFT(层序)
// 原型方法2:广度优先遍历-层序遍历-LeetCode102
CompleteBinaryTree.prototype.levelOrder = function (root) {
var result = [] // 最终的结果数组
// 当root为空时
if (root === null) return result
var queue = [root] // 定义一个队列,用于存放当前层级的节点
// 当队列中有元素
while (queue.length) {
var levelResult = [] // 每一层的结果数组(*循环一次需要清空)
// 1.记录当前元素个数,进行遍历
var len = queue.length
var curNode = null
for (var i = 0; i < len; i++) {
curNode = queue.shift()
levelResult.push(curNode.val)
// 2.向队列中添加下一层级的节点
// && 逻辑与,当表达式1为真,才会执行表达式2
curNode.left && queue.push(curNode.left)
curNode.right && queue.push(curNode.right)
}
// 3.把这一层的结果数组放到总结果的最后
result.push(levelResult)
}
return result
}
console.log(myTree.levelOrder(root)); // [[1], [2], [3], [4]]
3.深度优先遍历DFT(前、中、后序)
// 原型方法3:深度优先遍历-前序遍历-LeetCode144
CompleteBinaryTree.prototype.preOrderTraversal = function (root) {
var result = []
// 对当前节点进行处理
var dfs = function (root) {
if (root === null) return result
result.push(root.val)
dfs(root.left)
dfs(root.right)
}
dfs(root)
return result
}
console.log(myTree.preOrderTraversal(root)); // [1, 2, 3 ,4]
// 原型方法3:深度优先遍历-中序遍历-LeetCode94
CompleteBinaryTree.prototype.inOrderTraversal = function (root) {
var result = []
// 对当前节点进行处理
var dfs = function (root) {
if (root === null) return result
dfs(root.left)
result.push(root.val)
dfs(root.right)
}
dfs(root)
return result
}
console.log(myTree.inOrderTraversal(root)); // [1, 4, 3, 2]
// 原型方法4:深度优先遍历-后序遍历-LeetCode145
CompleteBinaryTree.prototype.postOrderTraversal = function (root) {
var result = []
// 对当前节点进行处理
var dfs = function (root) {
if (root === null) return result
dfs(root.left)
dfs(root.right)
result.push(root.val)
}
dfs(root)
return result
}
console.log(myTree.postOrderTraversal(root)); // [4, 3, 2, 1]
以上参考LeetCode题解 最后想提一个问题:层序遍历的结果和先序遍历的感觉是一样的?
(2021/8/17)自己解答:不一样,比如:[1, 2, null, 3, 4, 5],层序遍历的结果是[1, 2, 3, 4, 5];而先序遍历的结果是:[1, 2, 3, 5, 4];中序遍历的结果为[5, 3, 2, 4, 1];后序遍历的结果为[5, 3, 4, 2, 1]。
以及 使用const和let替换var