PK创意闹新春,我正在参加「春节创意投稿大赛」,详情请看:春节创意投稿大赛
二叉树 是基于树的数据结构, 它的每个节点至多含有2个子节点:左子节点 和 右子节点;
graph TB
root((根节点)) --> leftNode1((左子树))
root((根节点)) --> rightNode1((右子树))
leftNode1((左子树)) --> leftNode2((叶子结点))
leftNode1((左子树)) --> rightNode2((叶子结点))
rightNode1((右子树)) --> leftNode3((叶子结点))
rightNode1((右子树)) --> leftNode4((叶子结点))
基本的结构代码:
class TreeNode {
public value: number;
public left: TreeNode | null;
public right: TreeNode | null;
constructor(value?: number, left?: TreeNode | null, right?: TreeNode | null) {
this.value = value === undefined ? 0 : value;
this.left = left === undefined ? null : left
this.right = right === undefined ? null : right
}
}
示例: 一个 二叉树 [7, 4, 5, 1, 3, 6, 8]
graph TB
root((7)) --> leftNode1((4))
root((7)) --> rightNode1((5))
leftNode1((4)) --> leftNode2((1))
leftNode1((4)) --> rightNode2((3))
rightNode1((5)) --> leftNode3((6))
rightNode1((5)) --> leftNode4((8))
const nums: number[] = [7, 4, 5, 1, 3, 6, 8]
const root: TreeNode = new TreeNode(7)
const n: number = nums.length
function createTree (root: TreeNode, index: number) {
const leftIndex: number = 2 * index + 1
const rightIndex: number = leftIndex + 1
if (leftIndex < n) {
root.left = new TreeNode(nums[leftIndex])
createTree(root.left, leftIndex)
}
if (rightIndex < n) {
root.right = new TreeNode(nums[rightIndex])
createTree(root.right, rightIndex)
}
}
createTree(root, 0)
前序遍历
遍历顺序: 先访问 根节点 然后再遍历左子树,最后遍历右子树
比如示例的二叉树,前序遍历:[7,4,1,3,5,6,8]
function preorderTraversal (root: TreeNode | null): number[] {
if (!root) return []
const left: number[] = preorderTraversal(root.left)
const right: number[] = preorderTraversal(root.right)
return [root.value, ...left, ...right]
}
const res: number[] = preorderTraversal(root) // [7, 4, 1, 3, 5, 6, 8]
中序遍历
遍历顺序: 先访问 左子树 然后再遍历根节点,最后遍历右子树
比如示例的二叉树,中序遍历:[1,4,3,7,6,5,8]
function inorderTraversal(root: TreeNode | null): number[] {
if (!root) return []
const left: number[] = inorderTraversal(root.left)
const right: number[] = inorderTraversal(root.right)
return [...left, root.value, ...right]
}
const inRes: number[] = inorderTraversal(root) // [1, 4, 3, 7, 6, 5, 8]
后序遍历
遍历顺序: 先访问 左子树 然后再遍历右子树,最后遍历根节点
比如示例的二叉树,后序遍历:[1,3,4,6,8,5,7]
function postorderTraversal(root: TreeNode | null): number[] {
if (!root) return []
const left: number[] = postorderTraversal(root.left)
const right: number[] = postorderTraversal(root.right)
return [...left, ...right, root.value]
}
console.log(postorderTraversal(root)) // [1, 3, 4, 6, 8, 5, 7 ]
前序 / 后序 + 中序 会确定一个二叉树
- 后序 最后一个元素 为根元素
- 前序 第一个元素 为 根元素
前序 + 中序
// 前序 [7, 4, 1, 3, 5, 6, 8], 中序 [1, 4, 3, 7, 6, 5, 8]
function createBinaryTree (preorder: number[], inorder: number[]): TreeNode | null {
// 先遍历中序的索引
const in_map: Map<number, number> = new Map()
inorder.forEach((value, index) => {
in_map.set(value, index)
})
let pre_index: number = 0
function dsf (left: number, right: number): TreeNode | null {
console.log(left, right)
if (left > right) return null
const val: number = preorder[pre_index]
pre_index++
const node: TreeNode = new TreeNode(val)
const index: number = in_map.get(val) as number
node.left = dsf(left, index - 1)
node.right = dsf(index + 1, right)
return node
}
return dsf(0, preorder.length - 1)
}
console.log(createBinaryTree([7, 4, 1, 3, 5, 6, 8], [1, 4, 3, 7, 6, 5, 8]))
后序 + 中序
// 后序 [1, 3, 4, 6, 8, 5, 7 ], 中序 [1, 4, 3, 7, 6, 5, 8]
function createPostBinaryTree (postorder: number[], inorder: number[]): TreeNode | null {
// 先遍历中序的索引
const in_map: Map<number, number> = new Map()
inorder.forEach((value, index) => {
in_map.set(value, index)
})
let post_index: number = postorder.length - 1
function dsf (left: number, right: number): TreeNode | null {
if (left > right) return null
console.log(left, right)
const val: number = postorder[post_index]
post_index--
const node: TreeNode = new TreeNode(val)
const index: number = in_map.get(val) as number
node.right = dsf(index + 1, right)
node.left = dsf(left, index - 1)
return node
}
return dsf(0, postorder.length - 1)
}
console.log(createPostBinaryTree([1, 3, 4, 6, 8, 5, 7 ], [1, 4, 3, 7, 6, 5, 8]))
广度优先遍历
一层一层遍历
function bfs(root: TreeNode | null):number[] {
if (!root) return []
const result: number[] = []
const queue: TreeNode[] = [root]
while(queue.length) {
const node: TreeNode = queue.shift() as TreeNode
result.push(node.value)
if (node.left) {
queue.push(node.left)
}
if (node.right) {
queue.push(node.right)
}
}
return result
}
console.log(bfs(root)) // [7, 4, 5, 1, 3, 6, 8]
深度优先遍历
function dfs (root: TreeNode | null): number[]{
if (!root) return []
const result: number[] = []
const queue: TreeNode[] = [root]
while(queue.length) {
const node: TreeNode = queue.pop() as TreeNode
result.push(node.value)
if (node.right) {
queue.push(node.right)
}
if (node.left) {
queue.push(node.left)
}
}
return result
}
console.log(dfs(root)) // [7, 4, 1, 3, 5, 6, 8 ]